Kate’s DVG code
message("Loading packages")
Loading packages
library('plyr')
library('tidyverse')
library('reshape2')
library('ggpubr')
library('glue')
library('ggVennDiagram')
# paramters used when running divrge
grouping_param = 5
match_length_param = 28
readLength = 150
# deletion read count cutoffs
count_cut = 30
message("Setting work directory and input file names")
Setting work directory and input file names
wkdir = "/Users/marissaknoll/Desktop/GitHub/Obesity/NewExtractions/H9N2/DVGs"
setwd(wkdir)
if (!dir.exists(glue("{wkdir}/DVG_figures"))) {
dir.create(glue("{wkdir}/DVG_figures"))
}
saveitdir = glue("{wkdir}/DVG_figures")
source(glue('{wkdir}/scripts/obese_PlotPrep.R'))
# loading in metadata and coverage data
metafile = glue("{wkdir}/../H9_Metadata.csv")
meta = read.csv(file=metafile,header=T,sep=",",na.strings = c(''))
meta = filter(meta, resequenced == "yes") %>% filter(cohort != "ND")
transmission_info = "/Users/marissaknoll/Desktop/GitHub/Obesity/NewExtractions/H9N2/TransmissionPairs.csv"
pairs = read.csv(transmission_info, header = T)
meta = merge(meta, pairs, all.x = TRUE) %>% unique()
coverage_passfile = glue('{wkdir}/scripts/H9N2.coverage.pass.check.200.0.95.csv')
cov_check = read.csv(file=coverage_passfile,header=T,sep=",",na.strings = c(''))
# filter for samples that either pass with a yes OR has good average coverage and percentage cov at 200x is > 80
cov_filt_names = cov_check %>% filter(pass == 'YES' |
mean_coverage >= 200 |
percentage > 0.4) %>%
select(name, segment) %>%
unique()
# check segment count
cov_filt_names = cov_filt_names %>% group_by(name) %>% add_tally(name = 'segment_tally') %>%
ungroup() %>%
filter(segment_tally == 8) %>%
unique()
pull_names = c(levels(factor(cov_filt_names$name))) # list to pull names from
dvgfile = glue('{wkdir}/H9N2.DVG.FINAL.OneGap.N5.Mis2.M28.G5.csv') # dvg file
dvg = read.csv(file=dvgfile,header=T,sep=",",na.strings = c(''))
dvg = dvg %>% filter(name %in% pull_names) # filter for samples that pass our coverage checks
dvg$sample = dvg$name # generate new column so we can separate
dvg = dvg %>% separate(sample, c('new','cohort','ferret_id','dpi','rep'), '_') # separate into info
Warning: Expected 5 pieces. Missing pieces filled with `NA` in 40841 rows [200561, 200562, 200563, 200564, 200565, 200566, 200567, 200568, 200569, 200570, 200571, 200572, 200573, 200574, 200575, 200576, 200577, 200578, 200579, 200580, ...].
CONTROLS = dvg %>% filter(ferret_id == 'HK1073') # pulling out controls
CONTROLS$rep = CONTROLS$dpi
CONTROLS$dpi = 'stock' # adding in stock info
dvg = dvg %>% filter(!name %in% c(levels(factor(CONTROLS$name)))) %>% unique()
dvg = rbind(dvg, CONTROLS) # rbind everything so it is all in one dataframe
# prepping rep information
dvg = dvg %>% select(-SegTotalDVG, -new) %>% filter(DVG_freq >= count_cut) %>% unique() # filter for those that pass cutoffs
rep1 = dvg %>% filter(rep == 'rep1') %>% unique()
rep2 = dvg %>% filter(rep == 'rep2') %>% unique()
# merge reps into one
dvg_reps = merge(rep1, rep2, by = c('cohort','ferret_id','dpi',
'segment','segment_size','strain',
'DVG_group','NewGap',
'NewStart','NewEnd','GroupBoundaries',
'DeletionSize','EstimatedFragLength'), all = TRUE) %>% unique()
# add in zeros
dvg_reps$DVG_freq.x[is.na(dvg_reps$DVG_freq.x)] = 0
dvg_reps$DVG_freq.y[is.na(dvg_reps$DVG_freq.y)] = 0
ggplot(dvg_reps, aes(x=DVG_freq.x, y=DVG_freq.y)) +
geom_point() +
PlotTheme1

# number of samples?
levels(factor(dvg_reps$ferret_id)) %>% length()
[1] 42
# reorder by segment size
SEGMENTS = c('H9N2_PB2', 'H9N2_PB1',
'H9N2_PA','H9N2_HA','H9N2_NP',
'H9N2_NA','H9N2_MP','H9N2_NS')
cov_check$segment = factor(cov_check$segment, levels = SEGMENTS)
cov_check %>%
filter(name %in% pull_names) %>%
ggplot(., aes(x= segment, y = mean_coverage)) +
geom_boxplot() +
PlotTheme1

cov_check %>%
filter(name %in% pull_names) %>%
ggplot(., aes(x= segment, y = median_coverage)) +
geom_boxplot() +
PlotTheme1

cov_check %>%
filter(name %in% pull_names) %>%
ggplot(., aes(x= segment, y = percentage)) +
geom_boxplot() +
PlotTheme1

df = cov_filt_names %>% select(-segment, -segment_tally) %>% unique()
df$sample = df$name
df = df %>% separate(sample, c('new','cohort','ferret_id','dpi','rep'), '_')
Warning: Expected 5 pieces. Missing pieces filled with `NA` in 10 rows [35, 36, 50, 72, 85, 154, 166, 171, 188, 202].
CONTROLS = df %>% filter(ferret_id == 'HK1073')
CONTROLS$rep = CONTROLS$dpi
CONTROLS$dpi = 'stock'
df = df %>% filter(!name %in% c(levels(factor(CONTROLS$name)))) %>% unique()
df = rbind(df, CONTROLS)
r1 = df %>% filter(rep == 'rep1') %>% select(-new) %>% unique()
r2 = df %>% filter(rep == 'rep2') %>% select(-new) %>% unique()
reps = merge(r1, r2, by = c('cohort','ferret_id','dpi')) %>% unique()
# these are the samples that only had one rep!
setdiff(levels(factor(r1$ferret_id)),
levels(factor(r2$ferret_id)))
[1] "1411" "1972" "2244"
setdiff(meta$ferretID, reps$ferret_id) # samples in meta not in seq data
[1] "1411" "1971" "1972" "2235" "2244" "2867" "2868"
setdiff(reps$ferret_id, meta$ferretID) # samples in seq data not in meta
character(0)
m = merge(reps, meta, by.x = c('ferret_id','cohort'), by.y = c("ferretID","cohort"), all = TRUE) %>%
filter(inf_route %in% c('Index','Contact','Control'))
write.csv(m, glue('{wkdir}/scripts/UPDATED.H9N2.metadata.csv'), row.names = FALSE)
# type check - only stock index direct
print(levels(factor(m$inf_route)))
[1] "Contact" "Control" "Index"
m$inf_route = factor(m$inf_route, levels = c('Control','Index','Contact'))
m = m %>% filter(name.x != is.na(name.x)) %>% unique()
p1 = m %>% filter(!(is.na(pair_numbers))) %>% unique() %>%
ggplot(., aes(x= dpi, y = pair_numbers, fill = diet)) +
geom_tile(color = 'black') +
PlotTheme3 +
DietcolScale_fill +
facet_grid(pair_diets~inf_route, scales = 'free', space = 'free')
print(p1)
ggsave(p1,
filename = glue("{wkdir}/DVG_figures/final.samples.pdf"),
width = 6,
height = 6, limitsize=FALSE, useDingbats = FALSE)
ggsave(p1,
filename = glue("{wkdir}/DVG_figures/final.samples.png"),
width = 6,
height = 6, limitsize=FALSE) #, useDingbats = FALSE)

dvg_reps = dvg_reps %>%
filter(DVG_freq.x > count_cut & DVG_freq.y > count_cut) %>%
unique() # make sure that both reps pass our cutoff
# add in variables for plotting
dvg_reps$ferret_day = paste0(dvg_reps$ferret_id, '_', dvg_reps$dpi)
m$ferret_day = paste0(m$ferret_id, '_', m$dpi)
stock_temp = dvg_reps %>% filter(dpi == 'stock') %>%
group_by(ferret_id, cohort, dpi, segment, name.x, name.y) %>%
add_tally(name = 'seg_deletion_richness') %>%
unique() %>%
ungroup() %>%
group_by(ferret_id, dpi, name.x, name.y, cohort) %>%
add_tally(name = 'deletion_richness') %>%
ungroup() %>%
unique()
s = stock_temp # will use later
# filter down stock temp information
stock_temp = stock_temp %>%
select(ferret_id, dpi, cohort,ferret_day, segment, deletion_richness, seg_deletion_richness) %>%
unique()
stock_temp = merge(stock_temp, m, by = c('ferret_id', 'dpi','cohort','ferret_day')) %>%
unique()
# filter out stock information, calculate dvg richness by segment and across genome for samples
dr = dvg_reps %>%
filter(dpi != 'stock') %>%
unique() %>%
group_by(ferret_id, dpi, segment, name.x, name.y, cohort) %>%
add_tally(name = 'seg_deletion_richness') %>%
ungroup() %>%
group_by(ferret_id, dpi, name.x, name.y, cohort) %>%
add_tally(name = 'deletion_richness') %>%
ungroup() %>%
unique()
# filter down information so you don't have duplicates
richness = dr %>%
select(ferret_id, dpi, cohort,ferret_day, segment, deletion_richness, seg_deletion_richness) %>%
unique()
# merge with metadata info
#richness = merge(richness, m, by = c('ferret_id', 'dpi','cohort','ferret_day'), all.y = TRUE) %>% # CHANGED
richness = merge(richness, m, by = c('ferret_id', 'dpi','cohort','ferret_day'), all.x = TRUE) %>%
unique() %>%
filter(!is.na(inf_route))
# make sure we filter out stock information (will add using the 's' dataframe generated above)
richness = richness %>% filter(dpi != 'stock')
reps_df = rbind(dr, s) %>% unique() # final reps richness df
reps_df = merge(reps_df, m, by = c('ferret_id','dpi','cohort','ferret_day','name.x','rep.x','name.y','rep.y')) %>% unique() # add metadata
p4 = reps_df %>%
select(segment, NewGap, EstimatedFragLength, diet) %>%
unique() %>%
ggplot(., aes(x= EstimatedFragLength)) +
geom_histogram(color = 'black') +
PlotTheme1 +
labs(x="estimated DVG frag. length (nt)", y='number of unique DVG species')
print(p4)
ggsave(p4,
filename = glue("{wkdir}/DVG_figures/deletion.size.pdf"),
width = 5,
height = 5, limitsize=FALSE, useDingbats = FALSE)
ggsave(p4,
filename = glue("{wkdir}/DVG_figures/deletion.size.png"),
width =5,
height = 5, limitsize=FALSE) #, useDingbats = FALSE)

p4_alt = reps_df %>%
select(segment, NewGap, EstimatedFragLength, diet, inf_route) %>%
unique() %>%
ggplot(., aes(x= EstimatedFragLength)) +
geom_histogram(color = 'black', binwidth = 50) +
facet_grid(inf_route~diet) +
PlotTheme1 +
labs(x="estimated DVG frag. length (nt)", y='number of unique DVG species')
print(p4_alt)
ggsave(p4_alt,
filename = glue("{wkdir}/DVG_figures/deletion.size.bydiet.bytype.pdf"),
width = 10,
height = 5, limitsize=FALSE, useDingbats = FALSE)

lean_index = reps_df %>% filter(inf_route == 'Index' & diet == 'Lean') %>%
unique() %>%
group_by(NewGap, segment, NewStart, NewEnd) %>%
add_tally(name = 'lean_deletion_count') %>%
ungroup() %>%
select(NewGap, segment, lean_deletion_count) %>%
unique()
obese_index = reps_df %>% filter(inf_route == 'Index' & diet == 'Obese') %>%
unique() %>%
group_by(NewGap, segment, NewStart, NewEnd) %>%
add_tally(name = 'obese_deletion_count') %>%
ungroup() %>%
select(NewGap, segment, obese_deletion_count) %>%
unique()
df = merge(lean_index, obese_index, by = c('NewGap','segment'), all = TRUE)
head(df)
df$lean_deletion_count[is.na(df$lean_deletion_count)] = 0
df$obese_deletion_count[is.na(df$obese_deletion_count)] = 0
p8 = reps_df %>% filter(inf_route == 'Index') %>%
unique() %>%
group_by(NewGap, segment, NewStart, NewEnd) %>%
add_tally(name = 'sample_count') %>%
ungroup() %>%
select(NewGap, segment,sample_count) %>%
unique() %>%
ggplot(., aes(x=sample_count, y = ..count../sum(..count..))) +
geom_histogram(color ='black') +
labs(x='number of samples with DVG type', y='proportion of DVGs in dataset (index only)') +
PlotTheme1
print(p8)
ggsave(p8,
filename = glue("{wkdir}/DVG_figures/sample.count.histo.pdf"),
width = 5,
height = 5, limitsize=FALSE, useDingbats = FALSE)
ggsave(p8,
filename = glue("{wkdir}/DVG_figures/sample.count.histo.png"),
width =5,
height = 5, limitsize=FALSE) #, useDingbats = FALSE)

reps_df$ave_dvg_freq = (reps_df$DVG_freq.x + reps_df$DVG_freq.y)/2
reps_df = reps_df %>%
dplyr::arrange(ferret_day, ave_dvg_freq) %>%
dplyr::group_by(ferret_day) %>%
dplyr::mutate(order_number = row_number()) %>%
ungroup() %>%
unique()
reps_df %>%
dplyr::group_by(NewGap, segment, inf_route, diet) %>%
dplyr::mutate(mean_order = mean(order_number),
sample_count = n(),
min_order = min(order_number),
max_order = max(order_number),
median_ord = median(order_number)) %>%
ungroup() %>%
unique() %>%
select(segment, NewGap, mean_order, sample_count, min_order, max_order, median_ord, inf_route, diet) %>%
filter(sample_count > 1) %>%
unique() %>%
ggplot(., aes(y=mean_order, x = sample_count)) +
geom_point() +
PlotTheme1 +
facet_grid(.~diet + inf_route)

top_ten = reps_df %>% filter(order_number %in% c(1, 2,3 ,4, 5, 6, 7, 8, 9, 10)) %>% unique()
head(top_ten)
length(levels(factor(top_ten$NewGap)))
[1] 178
max(df$lean_deletion_count)
[1] 112
max(df$obese_deletion_count)
[1] 108
p9 = ggplot(df, aes(x=lean_deletion_count, y = obese_deletion_count)) +
geom_jitter(width = 0.1, height = 0.1, alpha = 0.3) +
geom_hline(yintercept = 0, linetype = 2, color = 'black') +
geom_hline(yintercept = 25, linetype = 2, color = 'red') +
geom_vline(xintercept = 0, linetype = 2, color = 'black') +
geom_vline(xintercept = 17, linetype = 2, color = 'red') +
labs(x= 'number of lean samples with DVG', y='number of obese samples with DVG') +
PlotTheme1
print(p9)
ggsave(p9,
filename = glue("{wkdir}/DVG_figures/sample.count.lean.v.obese.pdf"),
width = 5,
height = 5, limitsize=FALSE, useDingbats = FALSE)
ggsave(p9,
filename = glue("{wkdir}/DVG_figures/sample.count.lean.v.obese.png"),
width =5,
height = 5, limitsize=FALSE) #, useDingbats = FALSE)

richness = rbind(richness, stock_temp)
#richness$deletion_richness[is.na(richness$deletion_richness)] = 0
DAYS = c('stock','d02','d04','d06','d08','d10','d12')
richness$dpi = factor(richness$dpi, levels = DAYS)
richness %>% filter(dpi %in% c('d02','d04')) %>%
filter(inf_route == 'Index' | inf_route == 'Control') %>%
filter(!(is.na(inf_route))) %>%
select(ferret_id, dpi, deletion_richness, inf_route, diet, pair_diets, cohort) %>%
unique() %>%
group_by(ferret_id) %>%
add_tally(name = 'n') %>%
ungroup() %>%
filter(n >= 2) %>%
ungroup() %>%
unique() %>%
ggplot(., aes(x=dpi, y = deletion_richness, color = cohort, group=ferret_id, shape = diet)) +
#geom_boxplot() +
geom_line() +
geom_point(size = 2) +
PlotTheme1 +
scale_color_brewer(palette = 'Set1')

#DietcolScale +
#facet_grid(.~cohort)
p7 = richness %>% filter(dpi %in% c('d02','d04','d06')) %>%
filter(inf_route == 'Index' | inf_route == 'Control') %>%
select(ferret_id, dpi, deletion_richness, inf_route, diet, pair_diets, cohort) %>%
unique() %>%
group_by(ferret_id) %>%
add_tally(name = 'n') %>%
ungroup() %>%
filter(n >= 2) %>%
ungroup() %>%
unique() %>%
ggplot(., aes(x=dpi, y = deletion_richness, color = diet, group=ferret_id, shape = diet)) +
#geom_boxplot() +
geom_line() +
geom_point(size = 2) +
PlotTheme1 +
DietcolScale
#facet_grid(.~cohort)
print(p7)
ggsave(p7,
filename = glue("{wkdir}/DVG_figures/richness.index.pdf"),
width = 5,
height = 5, limitsize=FALSE, useDingbats = FALSE)
ggsave(p7,
filename = glue("{wkdir}/DVG_figures/richness.index.png"),
width =5,
height = 5, limitsize=FALSE) #, useDingbats = FALSE)

colnames(richness)
[1] "ferret_id" "dpi" "cohort" "ferret_day" "segment"
[6] "deletion_richness" "seg_deletion_richness" "name.x" "rep.x" "name.y"
[11] "rep.y" "DPI" "sample" "inf_route" "diet"
[16] "titer" "log10_titer" "HAI_21dpi" "Ct_Mgene" "resequenced"
[21] "pair_numbers" "pair_diets"
order_typeday = c('Control_stock',
'Index_d02','Index_d04','Index_d06','Index_d08','Index_d10','Index_d12',
'Contact_d02','Contact_d04','Contact_d06','Contact_d08','Contact_d10','Contact_d12')
richness$type_day = paste0(richness$inf_route, '_', richness$dpi)
richness$type_day = factor(richness$type_day, levels = order_typeday)
p2 = richness %>% filter(diet == 'Obese' & pair_diets == 'OB>OB') %>%
select(ferret_id, dpi, deletion_richness, inf_route, diet, pair_numbers, pair_diets, type_day) %>%
ungroup() %>%
unique() %>%
ggplot(., aes(x=type_day, y = deletion_richness, color = pair_numbers, group=pair_numbers)) +
#geom_boxplot() +
geom_line(size = 1) +
geom_point(size = 2) +
labs(x='dpi (by index case)', y='DVG richness') +
PlotTheme1 +
scale_color_brewer(palette = 'Set2') #+
#DietcolScale +
#facet_grid(.~inf_route)
print(p2)
ggsave(p2,
filename = glue("{wkdir}/DVG_figures/obese.to.obese.diversity.pdf"),
width = 8,
height = 6, limitsize=FALSE, useDingbats = FALSE)
ggsave(p2,
filename = glue("{wkdir}/DVG_figures/obese.to.obese.diversity.png"),
width =8,
height = 6, limitsize=FALSE) #, useDingbats = FALSE)

gen_rich = richness %>%
select(ferret_id, dpi, cohort,deletion_richness, inf_route, diet, pair_numbers, pair_diets, type_day) %>%
unique()
head(gen_rich)
gen_rich %>% filter(dpi %in% c('d02','d04','d06','stock')) %>%
filter(inf_route == 'Index' | inf_route == "Control") %>%
ggplot(., aes(x=diet, y = deletion_richness, group = diet)) +
geom_boxplot(outlier.shape = NA) +
geom_jitter(width = 0.2, aes(color = diet)) +
labs(x='segment',y='deletion richness') +
PlotTheme1 +
DietcolScale +
facet_grid(.~dpi)

Test for significance
o = filter(gen_rich, inf_route == "Index" & dpi == "d06" & diet == "Obese")
l = filter(gen_rich, inf_route == "Index" & dpi == "d06" & diet == "Lean")
t.test(o$deletion_richness,l$deletion_richness)
Welch Two Sample t-test
data: o$deletion_richness and l$deletion_richness
t = 0.66564, df = 5.7765, p-value = 0.5313
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
-39.95197 69.42816
sample estimates:
mean of x mean of y
68.57143 53.83333
seg_rich = richness %>% #filter(diet == 'obese' & pair_diets == 'obese_obese') %>%
select(ferret_id, dpi, seg_deletion_richness, inf_route, diet,
pair_numbers, pair_diets, type_day, segment) %>%
unique()
head(seg_rich)
temp = seg_rich %>% select(ferret_id, dpi, inf_route, diet, pair_numbers, type_day, pair_diets) %>% unique()
temp$H9N2_PB2 = 0
temp$H9N2_PB1 = 0
temp$H9N2_PA = 0
temp$H9N2_HA = 0
temp$H9N2_NP = 0
temp$H9N2_NA = 0
temp$H9N2_MP = 0
temp$H9N2_NS = 0
temp = pivot_longer(temp, cols = all_of(SEGMENTS), names_to = 'segment') %>% select(-value)
seg_rich = merge(seg_rich, temp, by = c('ferret_id', 'dpi', 'inf_route', 'diet', 'pair_numbers', 'pair_diets', 'type_day', 'segment'), all = TRUE)
seg_rich$seg_deletion_richness[is.na(seg_rich$seg_deletion_richness)] = 0
seg_rich$segment = factor(seg_rich$segment, levels = SEGMENTS)
head(seg_rich)
seg_rich %>% filter(ferret_id == 1787) %>% head()
richness %>% filter(ferret_id == 1787) %>% head()
temp %>% filter(ferret_id == 1787)
NA
p3 = seg_rich %>% filter(segment %in% SEGMENTS) %>%
ggplot(., aes(x=segment, y = seg_deletion_richness)) +
geom_boxplot() +
labs(x='segment',y='deletion richness') +
PlotTheme1
print(p3)
ggsave(p3,
filename = glue("{wkdir}/DVG_figures/segment.richness.pdf"),
width = 5,
height = 5, limitsize=FALSE, useDingbats = FALSE)
ggsave(p3,
filename = glue("{wkdir}/DVG_figures/segment.richness.png"),
width =5,
height = 5, limitsize=FALSE) #, useDingbats = FALSE)

seg_rich$seg_weight = paste0(seg_rich$segment, '_', seg_rich$diet)
seg_rich$diet = factor(seg_rich$diet, levels = c('Control','Lean','Obese'))
seg_rich %>% filter(segment %in% SEGMENTS) %>%
drop_na(inf_route) %>%
ggplot(., aes(x=segment, y = seg_deletion_richness, group = seg_weight, color = diet)) +
geom_boxplot() +
labs(x='segment',y='deletion richness') +
PlotTheme1 +
DietcolScale +
facet_grid(.~inf_route)

p6 = seg_rich %>% filter(segment %in% SEGMENTS & dpi %in% c('d02','d04','d06')) %>%
filter(inf_route == 'Index' | inf_route == "Control") %>%
ggplot(., aes(x=segment, y = seg_deletion_richness, group = seg_weight, color = diet)) +
geom_boxplot(outlier.shape = NA) +
labs(x='segment',y='deletion richness') +
PlotTheme1 +
DietcolScale +
facet_grid(.~dpi)
print(p6)
ggsave(p6,
filename = glue("{wkdir}/DVG_figures/segment.index.richness.pdf"),
width = 8,
height = 4, limitsize=FALSE, useDingbats = FALSE)
ggsave(p6,
filename = glue("{wkdir}/DVG_figures/segment.index.richness.png"),
width =8,
height = 4, limitsize=FALSE) #, useDingbats = FALSE)

IGNORE THIS SECTION - what it looked like before ferret diets were
corrected
# 1973, 1977, and 1986 are listed as obese when they are actually lean, and 1984 is listed as lean when it is actually obese
#seg_rich %>%
#filter(!inf_route %in% c('stock','lean','obese')) %>%
# drop_na(inf_route) %>%
# filter(ferret_id == 1408)
#old_obese = filter(seg_rich, ferret_id %in% c(1973, 1977, 1986)) %>% unique()
#old_obese$diet = "Obese"
#old_lean = filter(seg_rich,ferret_id == 1984) %>% unique()
#old_lean$diet = "Lean"
#old_same = filter(seg_rich, ferret_id != c(1973, 1977, 1986, 1984))
#deleteit = rbind(old_obese,old_lean,old_same)
#deleteit %>% filter(!ferret_id %in% c(1973, 1977,1986, 1984) &
# segment %in% SEGMENTS & dpi %in% c('d02','d04','d06','stock')) %>%
# drop_na(inf_route) %>%
# filter(inf_route == 'Index' | inf_route == "Control") %>%
# ggplot(., aes(x=segment, y = seg_deletion_richness, group = seg_weight, color = diet)) +
# geom_boxplot(outlier.shape = NA) +
# labs(x='segment',y='deletion richness') +
# PlotTheme1 +
# DietcolScale +
# facet_grid(.~dpi)
#seg_rich %>% filter(ferret_id %in% c(1973, 1977,1986, 1984) & dpi == 'd06') %>%
# select(ferret_id, segment, dpi, seg_deletion_richness)
Test for significance
o = filter(seg_rich, inf_route == "Index" & dpi == "d06" & segment == "H9N2_NS" & diet == "Obese")
l = filter(seg_rich, inf_route == "Index" & dpi == "d06" & segment == "H9N2_NS" & diet == "Lean")
t.test(o$seg_deletion_richness,l$seg_deletion_richness)
Welch Two Sample t-test
data: o$seg_deletion_richness and l$seg_deletion_richness
t = NaN, df = NaN, p-value = NA
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
NaN NaN
sample estimates:
mean of x mean of y
0 0
# Significance: none
seg_rich %>% filter(inf_route == 'Index' & segment %in% SEGMENTS) %>%
ungroup() %>%
unique() %>%
ggplot(., aes(x=type_day, y = seg_deletion_richness, color = segment, group=segment)) +
#geom_boxplot() +
geom_line(size = 1) +
geom_point(size = 2) +
labs(x='dpi (by index case)', y='DVG richness') +
PlotTheme1 +
scale_color_brewer(palette = 'Set2') +
#DietcolScale +
facet_grid(.~diet + ferret_id, scales = 'free', space = 'free')

p4 = seg_rich %>% filter(diet == 'Obese' & pair_diets == 'OB>OB' & segment %in% SEGMENTS) %>%
ungroup() %>%
unique() %>%
ggplot(., aes(x=type_day, y = seg_deletion_richness, color = segment, group=segment)) +
#geom_boxplot() +
geom_line(size = 1) +
geom_point(size = 2) +
labs(x='dpi (by index case)', y='DVG richness') +
PlotTheme1 +
scale_color_brewer(palette = 'Set2') +
#DietcolScale +
facet_grid(.~pair_numbers, scales = 'free', space = 'free')
print(p4)
ggsave(p4,
filename = glue("{wkdir}/DVG_figures/segment.obese.to.obese.richness.pdf"),
width = 12,
height = 4, limitsize=FALSE, useDingbats = FALSE)
ggsave(p4,
filename = glue("{wkdir}/DVG_figures/segment.obese.to.obese.richness.png"),
width =12,
height = 4, limitsize=FALSE) #, useDingbats = FALSE)

End of Kate’s code
Which DVGs are shared between stock and index?
reps_df$DVG = paste0(reps_df$segment,"_",reps_df$DVG_group)
F17_stock = filter(reps_df ,inf_route == "Control", cohort == "F17")
F17_stock_dvg = unique(F17_stock$DVG)
W17_stock = filter(reps_df ,inf_route == "Control", cohort == "W17")
W17_stock_dvg = unique(W17_stock$DVG)
Sm18_stock = filter(reps_df ,inf_route == "Control", cohort == "Sm18")
Sm18_stock_dvg = unique(Sm18_stock$DVG)
Sp19_stock = filter(reps_df ,inf_route == "Control", cohort == "Sp19")
Sp19_stock_dvg = unique(Sp19_stock$DVG)
Sp20_stock = filter(reps_df ,inf_route == "Control", cohort == "Sp20")
Sp20_stock_dvg = unique(Sp20_stock$DVG)
F17_index = filter(reps_df ,inf_route == "Index", cohort == "F17")
F17_index_dvg = unique(F17_index$DVG)
W17_index = filter(reps_df ,inf_route == "Index", cohort == "W17")
W17_index_dvg = unique(W17_index$DVG)
Sm18_index = filter(reps_df ,inf_route == "Index", cohort == "Sm18")
Sm18_index_dvg = unique(Sm18_index$DVG)
Sp19_index = filter(reps_df ,inf_route == "Index", cohort == "Sp19")
Sp19_index_dvg = unique(Sp19_index$DVG)
Sp20_index = filter(reps_df ,inf_route == "Index", cohort == "Sp20")
Sp20_index_dvg = unique(Sp20_index$DVG)
F17_shared = F17_index %>% filter(DVG %in% F17_stock_dvg) %>% filter((DVG %in% F17_index_dvg)) %>% unique()
F17_denovo = F17_index %>% filter((DVG %in% F17_index_dvg)) %>% filter(!(DVG %in% F17_stock_dvg)) %>% unique()
W17_shared = W17_index %>% filter(DVG %in% W17_stock_dvg) %>% filter((DVG %in% W17_index_dvg)) %>% unique()
W17_denovo = W17_index %>% filter((DVG %in% W17_index_dvg)) %>% filter(!(DVG %in% W17_stock_dvg)) %>% unique()
Sm18_shared = Sm18_index %>% filter(DVG %in% Sm18_stock_dvg) %>% filter((DVG %in% Sm18_index_dvg)) %>% unique()
Sm18_denovo = Sm18_index %>% filter((DVG %in% Sm18_index_dvg)) %>% filter(!(DVG %in% Sm18_stock_dvg)) %>% unique()
Sp19_shared = Sp19_index %>% filter(DVG %in% Sp19_stock_dvg) %>% filter((DVG %in% Sp19_index_dvg)) %>% unique()
Sp19_denovo = Sp19_index %>% filter((DVG %in% Sp19_index_dvg)) %>% filter(!(DVG %in% Sp19_stock_dvg)) %>% unique()
Sp20_shared = Sp20_index %>% filter(DVG %in% Sp20_stock_dvg) %>% filter((DVG %in% Sp20_index_dvg)) %>% unique() # still not working
Sp20_denovo = Sp20_index %>% filter((DVG %in% Sp20_index_dvg)) %>% filter(!(DVG %in% Sp20_stock_dvg)) %>% unique() # still not working
stock_shared = rbind(F17_shared,W17_shared,Sm18_shared,Sp19_shared,Sp20_shared)
index_unique = rbind(F17_denovo,W17_denovo,Sm18_denovo,Sp19_denovo,Sp20_denovo)
stock_obese = filter(stock_shared, diet == "Obese")
o_dvg = unique(stock_obese$DVG)
stock_lean = filter(stock_shared, diet == "Lean")
l_dvg = unique(stock_lean$DVG)
stock_dvg <- list(Obese = o_dvg, Lean = l_dvg)
StockDVGs = ggVennDiagram(stock_dvg)
print(StockDVGs)
ggsave(StockDVGs, file = "StockDVGs.pdf", path = saveitdir)
Saving 7.29 x 4.51 in image

#ShockSharedDVGs = ggplot(stock_shared, aes(x = dpi, y = DVG)) +
# geom_point() +
# geom_line(aes(group = DVG)) +
# facet_grid(~segment) +
# PlotTheme1
#print(ShockSharedDVGs)
#ggsave(ShockSharedDVGs, file = "ShockSharedDVGs.pdf", path = saveitdir)
Are there diet-specific DVGs in index ferrets?
index_obese = filter(index_unique, diet == "Obese")
o_dvg = unique(index_obese$DVG)
index_lean = filter(index_unique, diet == "Lean")
l_dvg = unique(index_lean$DVG)
diet_dvg <- list(Obese = o_dvg, Lean = l_dvg)
DietUniqueDVGs = ggVennDiagram(diet_dvg)
print(DietUniqueDVGs)
ggsave(DietUniqueDVGs, file = "DietUniqueDVGs.pdf", path = saveitdir)
Saving 7.29 x 4.51 in image

Pulling out diet-specific DVGs
lean = index_lean %>%
filter(DVG %in% l_dvg) %>%
filter(!(DVG %in% o_dvg)) %>%
unique()
lean = lean %>%
group_by(DVG) %>%
mutate(count = 1, totalsamp = sum(count))
mult_lean = filter(lean, totalsamp > 1) %>%
unique()
obese = index_unique %>%
filter((DVG %in% o_dvg)) %>%
filter(!(DVG %in% l_dvg)) %>%
unique()
obese = obese %>%
group_by(DVG) %>%
mutate(count = 1, totalsamp = sum(count))
mult_obese = filter(obese, totalsamp > 1) %>%
unique()
lean_uniques = lean %>%
ungroup() %>%
select(segment,DVG_group,GroupBoundaries,totalsamp) %>%
unique() %>%
arrange(desc(totalsamp))
obese_uniques = obese %>%
ungroup() %>%
select(segment,DVG_group,GroupBoundaries,totalsamp) %>%
unique() %>%
arrange(desc(totalsamp))
lean_DVG_sizes = lean %>% ungroup %>% select(DVG,DVG_group, DeletionSize, NewStart, NewEnd, diet) %>%
unique() %>%
arrange(desc(DeletionSize)) %>%
mutate(name = factor(DVG, levels = unique(DVG)))
#ggplot(lean_DVG_sizes, aes(x = DeletionSize, y = name)) +
# geom_col() +
#facet_grid(segment~strain) +
# PlotTheme1
#ggsave("test_dvg.pdf", a, path = saveitdir, height = 30, width = 5)
#lean_DVG_sizes_plot = ggplot(lean_DVG_sizes, aes(x = NewStart, xend = NewEnd, y = name, yend = name, color = diet)) +
# geom_segment() +
#facet_grid(segment~strain) +
# PlotTheme1 +
# DietcolScale
#print(lean_DVG_sizes_plot)
#ggsave("lean_DVG_sizes_plot.pdf",lean_DVG_sizes_plot, path = saveitdir, height = 10, width = 10)
lean_DVG_size_seg = lean %>% ungroup %>% select(DVG,DVG_group, DeletionSize, NewStart, NewEnd, segment,diet) %>%
unique() %>%
arrange(desc(segment),desc(DeletionSize)) %>%
mutate(name = factor(DVG, levels = unique(DVG)))
lean_DVG_size_seg_plot = ggplot(filter(lean_DVG_size_seg, DeletionSize > 400),
aes(x = NewStart, xend = NewEnd, y = name, yend = name, color = diet)) +
geom_segment() +
facet_grid(~segment) +
PlotTheme1 +
DietcolScale
print(lean_DVG_size_seg_plot)
ggsave("lean_DVG_size_seg_plot.pdf",lean_DVG_size_seg_plot,path = saveitdir, height = 10, width = 10)

lean_indels_size_seg_plot = ggplot(filter(lean_DVG_size_seg, DeletionSize < 400),
aes(x = NewStart, xend = NewEnd, y = name, yend = name, color = diet)) +
geom_segment() +
facet_grid(~segment) +
PlotTheme1 +
DietcolScale
print(lean_indels_size_seg_plot)
ggsave("lean_indels_size_seg_plot.pdf",lean_indels_size_seg_plot,path = saveitdir, height = 10, width = 10)

obese_DVG_sizes = obese %>% ungroup %>% select(DVG,DVG_group, DeletionSize, NewStart, NewEnd, diet) %>%
unique() %>%
arrange(desc(DeletionSize)) %>%
mutate(name = factor(DVG, levels = unique(DVG)))
#ggplot(obese_DVG_sizes, aes(x = DeletionSize, y = name)) +
# geom_col() +
#facet_grid(segment~strain) +
# PlotTheme1
#ggsave("test_dvg.pdf", a, path = saveitdir, height = 30, width = 5)
#obese_DVG_sizes_plot = ggplot(obese_DVG_sizes, aes(x = NewStart, xend = NewEnd, y = name, yend = name, color = diet)) +
# geom_segment() +
#facet_grid(segment~strain) +
# PlotTheme1 +
# DietcolScale
#print(obese_DVG_sizes_plot)
#ggsave("obese_DVG_sizes_plot.pdf",obese_DVG_sizes_plot, path = saveitdir, height = 10, width = 10)
obese_DVG_size_seg = obese %>% ungroup %>% select(DVG,DVG_group, DeletionSize, NewStart, NewEnd, segment,diet) %>%
unique() %>%
arrange(desc(segment),desc(DeletionSize)) %>%
mutate(name = factor(DVG, levels = unique(DVG)))
obese_DVG_size_seg_plot = ggplot(filter(obese_DVG_size_seg, DeletionSize > 400),
aes(x = NewStart, xend = NewEnd, y = name, yend = name, color = diet)) +
geom_segment() +
facet_grid(~segment) +
PlotTheme1 +
DietcolScale
print(obese_DVG_size_seg_plot)
ggsave("obese_DVG_size_seg_plot.pdf",obese_DVG_size_seg_plot, path = saveitdir, height = 10, width = 10)

obese_indels_size_seg_plot = ggplot(filter(obese_DVG_size_seg, DeletionSize < 400),
aes(x = NewStart, xend = NewEnd, y = name, yend = name, color = diet)) +
geom_segment() +
facet_grid(~segment) +
PlotTheme1 +
DietcolScale
print(obese_indels_size_seg_plot)
ggsave("obese_indels_size_seg_plot.pdf",obese_indels_size_seg_plot, path = saveitdir, height = 10, width = 10)

Are DVGs transmitted?
dvg_df = select(reps_df, ferret_day, ferret_id, dpi, diet, inf_route, segment, DVG_group, GroupBoundaries, pair_diets, pair_numbers) %>%
ungroup() %>%
unique()
dvg_df$seg_dvg = paste0(dvg_df$segment,"_",dvg_df$DVG_group)
index = filter(dvg_df, inf_route == "Index") %>% unique()
first_time = c("1794_d04","1797_d02","1913_d06","1914_d06","1980_d02","1981_d10","1986_d10","2231_d06","2232_d02","2239_d02")
early_time = c("1794_d04","1797_d02","1980_d02","2232_d02","2239_d02")
direct = filter(dvg_df, ferret_day %in% first_time) %>% unique()
samples = unique(index$ferret_day)
dvg_transmitted = data.frame()
for(i in samples){
print(i)
n = filter(index, ferret_day == i)
partner = unique(n$pair_numbers)
d = filter(direct, pair_numbers %in% partner)
if(nrow(d) > 0){
s = unique(d$ferret_day)
print(s)
comp = merge(n, d, by = c("pair_diets","pair_numbers","segment","seg_dvg","DVG_group","GroupBoundaries"), all.x = TRUE) %>%
dplyr::count(pair_numbers,ferret_day.x, ferret_day.y)
colnames(comp) = c("pair_numbers","Index","Contact","count")
dvg_transmitted = rbind(dvg_transmitted, comp)
}else(print("No transmission"))
}
[1] "1408_d02"
[1] "No transmission"
[1] "1408_d04"
[1] "No transmission"
[1] "1408_d06"
[1] "No transmission"
[1] "1412_d08"
[1] "No transmission"
[1] "1414_d04"
[1] "No transmission"
[1] "1414_d06"
[1] "No transmission"
[1] "1416_d02"
[1] "No transmission"
[1] "1416_d04"
[1] "No transmission"
[1] "1789_d02"
[1] "1794_d04"
[1] "1789_d04"
[1] "1794_d04"
[1] "1800_d02"
[1] "No transmission"
[1] "1800_d04"
[1] "No transmission"
[1] "1800_d06"
[1] "No transmission"
[1] "1801_d02"
[1] "1797_d02"
[1] "1801_d04"
[1] "1797_d02"
[1] "1910_d02"
[1] "No transmission"
[1] "1912_d02"
[1] "1914_d06"
[1] "1912_d04"
[1] "1914_d06"
[1] "1912_d06"
[1] "1914_d06"
[1] "1968_d02"
[1] "No transmission"
[1] "1970_d02"
[1] "1981_d10"
[1] "1973_d02"
[1] "1986_d10"
[1] "1973_d06"
[1] "1986_d10"
[1] "1974_d02"
[1] "No transmission"
[1] "1974_d04"
[1] "No transmission"
[1] "1975_d04"
[1] "No transmission"
[1] "1975_d06"
[1] "No transmission"
[1] "1977_d02"
[1] "No transmission"
[1] "1977_d06"
[1] "No transmission"
[1] "1984_d02"
[1] "No transmission"
[1] "1984_d04"
[1] "No transmission"
[1] "2232_d02"
[1] "2232_d02"
[1] "2232_d06"
[1] "2232_d02"
[1] "2232_d08"
[1] "2232_d02"
[1] "2233_d04"
[1] "2232_d02"
[1] "2234_d04"
[1] "No transmission"
[1] "2239_d02"
[1] "2239_d02"
[1] "2239_d06"
[1] "2239_d02"
[1] "2239_d08"
[1] "2239_d02"
[1] "2239_d10"
[1] "2239_d02"
[1] "2240_d04"
[1] "2239_d02"
[1] "2251_d04"
[1] "No transmission"
[1] "2251_d06"
[1] "No transmission"
[1] "2253_d04"
[1] "2231_d06"
[1] "2253_d08"
[1] "2231_d06"
[1] "2254_d02"
[1] "No transmission"
[1] "2254_d04"
[1] "No transmission"
[1] "2254_d06"
[1] "No transmission"
[1] "2254_d08"
[1] "No transmission"
#dvg_transmitted = dvg_transmitted %>%
# pivot_wider(names_from = contact, values_from = count)
contact_dvgs = filter(dvg_df, inf_route == "Index") %>% dplyr::count(ferret_id,dpi,diet) %>%
ggplot(., aes(x = dpi, y = n, color = diet)) +
geom_point() +
geom_line(aes(group = ferret_id)) +
facet_grid(~ferret_id) +
ylab("DVG richness") +
xlab("DPI") +
PlotTheme1 +
DietcolScale
print(contact_dvgs)
ggsave(contact_dvgs, file = "contact_dvgs.pdf", path = saveitdir)
Saving 7.29 x 4.51 in image

LS0tCnRpdGxlOiAiRFZHX0FuYWx5c2lzIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpLYXRlJ3MgRFZHIGNvZGUKCmBgYHtyfQptZXNzYWdlKCJMb2FkaW5nIHBhY2thZ2VzIikKbGlicmFyeSgncGx5cicpCmxpYnJhcnkoJ3RpZHl2ZXJzZScpCmxpYnJhcnkoJ3Jlc2hhcGUyJykKbGlicmFyeSgnZ2dwdWJyJykKbGlicmFyeSgnZ2x1ZScpCmxpYnJhcnkoJ2dnVmVubkRpYWdyYW0nKQpgYGAKCmBgYHtyfQojIHBhcmFtdGVycyB1c2VkIHdoZW4gcnVubmluZyBkaXZyZ2UKZ3JvdXBpbmdfcGFyYW0gPSA1Cm1hdGNoX2xlbmd0aF9wYXJhbSA9IDI4CnJlYWRMZW5ndGggPSAxNTAKCiMgZGVsZXRpb24gcmVhZCBjb3VudCBjdXRvZmZzCmNvdW50X2N1dCA9IDMwCmBgYAoKYGBge3J9Cm1lc3NhZ2UoIlNldHRpbmcgd29yayBkaXJlY3RvcnkgYW5kIGlucHV0IGZpbGUgbmFtZXMiKQp3a2RpciA9ICIvVXNlcnMvbWFyaXNzYWtub2xsL0Rlc2t0b3AvR2l0SHViL09iZXNpdHkvTmV3RXh0cmFjdGlvbnMvSDlOMi9EVkdzIgpzZXR3ZCh3a2RpcikKYGBgCgpgYGB7cn0KaWYgKCFkaXIuZXhpc3RzKGdsdWUoInt3a2Rpcn0vRFZHX2ZpZ3VyZXMiKSkpIHsKICAgICAgICBkaXIuY3JlYXRlKGdsdWUoInt3a2Rpcn0vRFZHX2ZpZ3VyZXMiKSkKICAgICAgfQoKc2F2ZWl0ZGlyID0gZ2x1ZSgie3drZGlyfS9EVkdfZmlndXJlcyIpCmBgYAoKYGBge3J9CnNvdXJjZShnbHVlKCd7d2tkaXJ9L3NjcmlwdHMvb2Jlc2VfUGxvdFByZXAuUicpKQpgYGAKCmBgYHtyfQojIGxvYWRpbmcgaW4gbWV0YWRhdGEgYW5kIGNvdmVyYWdlIGRhdGEKbWV0YWZpbGUgPSBnbHVlKCJ7d2tkaXJ9Ly4uL0g5X01ldGFkYXRhLmNzdiIpCm1ldGEgPSByZWFkLmNzdihmaWxlPW1ldGFmaWxlLGhlYWRlcj1ULHNlcD0iLCIsbmEuc3RyaW5ncyA9IGMoJycpKSAKbWV0YSA9IGZpbHRlcihtZXRhLCByZXNlcXVlbmNlZCA9PSAieWVzIikgJT4lIGZpbHRlcihjb2hvcnQgIT0gIk5EIikKCnRyYW5zbWlzc2lvbl9pbmZvID0gIi9Vc2Vycy9tYXJpc3Nha25vbGwvRGVza3RvcC9HaXRIdWIvT2Jlc2l0eS9OZXdFeHRyYWN0aW9ucy9IOU4yL1RyYW5zbWlzc2lvblBhaXJzLmNzdiIKcGFpcnMgPSByZWFkLmNzdih0cmFuc21pc3Npb25faW5mbywgaGVhZGVyID0gVCkKCm1ldGEgPSBtZXJnZShtZXRhLCBwYWlycywgYWxsLnggPSBUUlVFKSAlPiUgdW5pcXVlKCkKCmNvdmVyYWdlX3Bhc3NmaWxlID0gZ2x1ZSgne3drZGlyfS9zY3JpcHRzL0g5TjIuY292ZXJhZ2UucGFzcy5jaGVjay4yMDAuMC45NS5jc3YnKQpjb3ZfY2hlY2sgPSByZWFkLmNzdihmaWxlPWNvdmVyYWdlX3Bhc3NmaWxlLGhlYWRlcj1ULHNlcD0iLCIsbmEuc3RyaW5ncyA9IGMoJycpKQpgYGAKCmBgYHtyfQojIGZpbHRlciBmb3Igc2FtcGxlcyB0aGF0IGVpdGhlciBwYXNzIHdpdGggYSB5ZXMgT1IgaGFzIGdvb2QgYXZlcmFnZSBjb3ZlcmFnZSBhbmQgcGVyY2VudGFnZSBjb3YgYXQgMjAweCBpcyA+IDgwCmNvdl9maWx0X25hbWVzID0gY292X2NoZWNrICU+JSBmaWx0ZXIocGFzcyA9PSAnWUVTJyB8IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYW5fY292ZXJhZ2UgPj0gMjAwICB8IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBlcmNlbnRhZ2UgPiAwLjQpICU+JSAKICAgICAgICAgICAgc2VsZWN0KG5hbWUsIHNlZ21lbnQpICU+JSAKICAgICAgICAgICAgdW5pcXVlKCkKCiMgY2hlY2sgc2VnbWVudCBjb3VudApjb3ZfZmlsdF9uYW1lcyA9IGNvdl9maWx0X25hbWVzICU+JSBncm91cF9ieShuYW1lKSAlPiUgYWRkX3RhbGx5KG5hbWUgPSAnc2VnbWVudF90YWxseScpICU+JSAKICAgICAgICAgICAgICAgICAgICB1bmdyb3VwKCkgJT4lIAogICAgICAgICAgICAgICAgICAgIGZpbHRlcihzZWdtZW50X3RhbGx5ID09IDgpICU+JSAKICAgICAgICAgICAgICAgICAgICB1bmlxdWUoKSAKCnB1bGxfbmFtZXMgPSBjKGxldmVscyhmYWN0b3IoY292X2ZpbHRfbmFtZXMkbmFtZSkpKSAgIyBsaXN0IHRvIHB1bGwgbmFtZXMgZnJvbQpgYGAKCmBgYHtyfQpkdmdmaWxlID0gZ2x1ZSgne3drZGlyfS9IOU4yLkRWRy5GSU5BTC5PbmVHYXAuTjUuTWlzMi5NMjguRzUuY3N2JykgIyBkdmcgZmlsZQpkdmcgPSByZWFkLmNzdihmaWxlPWR2Z2ZpbGUsaGVhZGVyPVQsc2VwPSIsIixuYS5zdHJpbmdzID0gYygnJykpCgpkdmcgPSBkdmcgJT4lIGZpbHRlcihuYW1lICVpbiUgcHVsbF9uYW1lcykgIyBmaWx0ZXIgZm9yIHNhbXBsZXMgdGhhdCBwYXNzIG91ciBjb3ZlcmFnZSBjaGVja3MKZHZnJHNhbXBsZSA9IGR2ZyRuYW1lICAjIGdlbmVyYXRlIG5ldyBjb2x1bW4gc28gd2UgY2FuIHNlcGFyYXRlCmR2ZyA9IGR2ZyAlPiUgc2VwYXJhdGUoc2FtcGxlLCBjKCduZXcnLCdjb2hvcnQnLCdmZXJyZXRfaWQnLCdkcGknLCdyZXAnKSwgJ18nKSAgIyBzZXBhcmF0ZSBpbnRvIGluZm8KCkNPTlRST0xTID0gZHZnICU+JSBmaWx0ZXIoZmVycmV0X2lkID09ICdISzEwNzMnKSAgIyBwdWxsaW5nIG91dCBjb250cm9scwpDT05UUk9MUyRyZXAgPSBDT05UUk9MUyRkcGkKQ09OVFJPTFMkZHBpID0gJ3N0b2NrJyAgIyBhZGRpbmcgaW4gc3RvY2sgaW5mbwoKZHZnID0gZHZnICU+JSBmaWx0ZXIoIW5hbWUgJWluJSBjKGxldmVscyhmYWN0b3IoQ09OVFJPTFMkbmFtZSkpKSkgJT4lIHVuaXF1ZSgpCgpkdmcgPSByYmluZChkdmcsIENPTlRST0xTKSAjIHJiaW5kIGV2ZXJ5dGhpbmcgc28gaXQgaXMgYWxsIGluIG9uZSBkYXRhZnJhbWUKYGBgCgpgYGB7cn0KIyBwcmVwcGluZyByZXAgaW5mb3JtYXRpb24KZHZnID0gZHZnICU+JSBzZWxlY3QoLVNlZ1RvdGFsRFZHLCAtbmV3KSAlPiUgZmlsdGVyKERWR19mcmVxID49IGNvdW50X2N1dCkgJT4lIHVuaXF1ZSgpICAjIGZpbHRlciBmb3IgdGhvc2UgdGhhdCBwYXNzIGN1dG9mZnMKcmVwMSA9IGR2ZyAlPiUgZmlsdGVyKHJlcCA9PSAncmVwMScpICU+JSB1bmlxdWUoKQpyZXAyID0gZHZnICU+JSBmaWx0ZXIocmVwID09ICdyZXAyJykgJT4lIHVuaXF1ZSgpCmBgYAoKYGBge3J9CiMgbWVyZ2UgcmVwcyBpbnRvIG9uZQpkdmdfcmVwcyA9IG1lcmdlKHJlcDEsIHJlcDIsIGJ5ID0gYygnY29ob3J0JywnZmVycmV0X2lkJywnZHBpJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc2VnbWVudCcsJ3NlZ21lbnRfc2l6ZScsJ3N0cmFpbicsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0RWR19ncm91cCcsJ05ld0dhcCcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ05ld1N0YXJ0JywnTmV3RW5kJywnR3JvdXBCb3VuZGFyaWVzJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnRGVsZXRpb25TaXplJywnRXN0aW1hdGVkRnJhZ0xlbmd0aCcpLCBhbGwgPSBUUlVFKSAlPiUgdW5pcXVlKCkKYGBgCgpgYGB7cn0KIyBhZGQgaW4gemVyb3MKZHZnX3JlcHMkRFZHX2ZyZXEueFtpcy5uYShkdmdfcmVwcyREVkdfZnJlcS54KV0gPSAwCmR2Z19yZXBzJERWR19mcmVxLnlbaXMubmEoZHZnX3JlcHMkRFZHX2ZyZXEueSldID0gMApgYGAKCmBgYHtyfQpnZ3Bsb3QoZHZnX3JlcHMsIGFlcyh4PURWR19mcmVxLngsIHk9RFZHX2ZyZXEueSkpICsgCiAgICBnZW9tX3BvaW50KCkgKyAKICAgIFBsb3RUaGVtZTEKYGBgCgpgYGB7cn0KIyBudW1iZXIgb2Ygc2FtcGxlcz8KbGV2ZWxzKGZhY3RvcihkdmdfcmVwcyRmZXJyZXRfaWQpKSAlPiUgbGVuZ3RoKCkKYGBgCgpgYGB7cn0KIyByZW9yZGVyIGJ5IHNlZ21lbnQgc2l6ZQpTRUdNRU5UUyA9IGMoJ0g5TjJfUEIyJywgJ0g5TjJfUEIxJywKICAgICAgICAgICAgJ0g5TjJfUEEnLCdIOU4yX0hBJywnSDlOMl9OUCcsIAogICAgICAgICAgICAnSDlOMl9OQScsJ0g5TjJfTVAnLCdIOU4yX05TJykKCmNvdl9jaGVjayRzZWdtZW50ID0gZmFjdG9yKGNvdl9jaGVjayRzZWdtZW50LCBsZXZlbHMgPSBTRUdNRU5UUykKYGBgCgpgYGB7cn0KY292X2NoZWNrICU+JSAKICAgIGZpbHRlcihuYW1lICVpbiUgcHVsbF9uYW1lcykgJT4lCiAgICBnZ3Bsb3QoLiwgYWVzKHg9IHNlZ21lbnQsIHkgPSBtZWFuX2NvdmVyYWdlKSkgKyAKICAgIGdlb21fYm94cGxvdCgpICsgCiAgICBQbG90VGhlbWUxCgpjb3ZfY2hlY2sgJT4lIAogICAgZmlsdGVyKG5hbWUgJWluJSBwdWxsX25hbWVzKSAlPiUKICAgIGdncGxvdCguLCBhZXMoeD0gc2VnbWVudCwgeSA9IG1lZGlhbl9jb3ZlcmFnZSkpICsgCiAgICBnZW9tX2JveHBsb3QoKSArIAogICAgUGxvdFRoZW1lMQoKY292X2NoZWNrICU+JSAKICAgIGZpbHRlcihuYW1lICVpbiUgcHVsbF9uYW1lcykgJT4lCiAgICBnZ3Bsb3QoLiwgYWVzKHg9IHNlZ21lbnQsIHkgPSBwZXJjZW50YWdlKSkgKyAKICAgIGdlb21fYm94cGxvdCgpICsgCiAgICBQbG90VGhlbWUxCmBgYAoKYGBge3J9CmRmID0gY292X2ZpbHRfbmFtZXMgJT4lIHNlbGVjdCgtc2VnbWVudCwgLXNlZ21lbnRfdGFsbHkpICU+JSB1bmlxdWUoKQpkZiRzYW1wbGUgPSBkZiRuYW1lCmRmID0gZGYgJT4lIHNlcGFyYXRlKHNhbXBsZSwgYygnbmV3JywnY29ob3J0JywnZmVycmV0X2lkJywnZHBpJywncmVwJyksICdfJykKCkNPTlRST0xTID0gZGYgJT4lIGZpbHRlcihmZXJyZXRfaWQgPT0gJ0hLMTA3MycpCkNPTlRST0xTJHJlcCA9IENPTlRST0xTJGRwaQpDT05UUk9MUyRkcGkgPSAnc3RvY2snCgpkZiA9IGRmICU+JSBmaWx0ZXIoIW5hbWUgJWluJSBjKGxldmVscyhmYWN0b3IoQ09OVFJPTFMkbmFtZSkpKSkgJT4lIHVuaXF1ZSgpCmRmID0gcmJpbmQoZGYsIENPTlRST0xTKQoKcjEgPSBkZiAlPiUgZmlsdGVyKHJlcCA9PSAncmVwMScpICU+JSBzZWxlY3QoLW5ldykgJT4lIHVuaXF1ZSgpCnIyID0gZGYgJT4lIGZpbHRlcihyZXAgPT0gJ3JlcDInKSAlPiUgc2VsZWN0KC1uZXcpICU+JSB1bmlxdWUoKQpyZXBzID0gbWVyZ2UocjEsIHIyLCBieSA9IGMoJ2NvaG9ydCcsJ2ZlcnJldF9pZCcsJ2RwaScpKSAlPiUgdW5pcXVlKCkKCiMgdGhlc2UgYXJlIHRoZSBzYW1wbGVzIHRoYXQgb25seSBoYWQgb25lIHJlcCEKc2V0ZGlmZihsZXZlbHMoZmFjdG9yKHIxJGZlcnJldF9pZCkpLAogICAgICAgbGV2ZWxzKGZhY3RvcihyMiRmZXJyZXRfaWQpKSkKYGBgCgpgYGB7cn0Kc2V0ZGlmZihtZXRhJGZlcnJldElELCByZXBzJGZlcnJldF9pZCkgICMgc2FtcGxlcyBpbiBtZXRhIG5vdCBpbiBzZXEgZGF0YQpzZXRkaWZmKHJlcHMkZmVycmV0X2lkLCBtZXRhJGZlcnJldElEKSAjIHNhbXBsZXMgaW4gc2VxIGRhdGEgbm90IGluIG1ldGEKCm0gPSBtZXJnZShyZXBzLCBtZXRhLCBieS54ID0gYygnZmVycmV0X2lkJywnY29ob3J0JyksIGJ5LnkgPSBjKCJmZXJyZXRJRCIsImNvaG9ydCIpLCBhbGwgPSBUUlVFKSAlPiUgCiAgZmlsdGVyKGluZl9yb3V0ZSAlaW4lIGMoJ0luZGV4JywnQ29udGFjdCcsJ0NvbnRyb2wnKSkKICAgICAgICAgCndyaXRlLmNzdihtLCBnbHVlKCd7d2tkaXJ9L3NjcmlwdHMvVVBEQVRFRC5IOU4yLm1ldGFkYXRhLmNzdicpLCByb3cubmFtZXMgPSBGQUxTRSkKYGBgCgpgYGB7cn0KIyB0eXBlIGNoZWNrIC0gb25seSBzdG9jayBpbmRleCBkaXJlY3QKcHJpbnQobGV2ZWxzKGZhY3RvcihtJGluZl9yb3V0ZSkpKQpgYGAKCmBgYHtyfQptJGluZl9yb3V0ZSA9IGZhY3RvcihtJGluZl9yb3V0ZSwgbGV2ZWxzID0gYygnQ29udHJvbCcsJ0luZGV4JywnQ29udGFjdCcpKQoKbSA9IG0gJT4lIGZpbHRlcihuYW1lLnggIT0gaXMubmEobmFtZS54KSkgJT4lIHVuaXF1ZSgpCmBgYAoKYGBge3J9CnAxID0gbSAlPiUgZmlsdGVyKCEoaXMubmEocGFpcl9udW1iZXJzKSkpICU+JSB1bmlxdWUoKSAlPiUgCiAgICBnZ3Bsb3QoLiwgYWVzKHg9IGRwaSwgeSA9IHBhaXJfbnVtYmVycywgZmlsbCA9IGRpZXQpKSArIAogICAgZ2VvbV90aWxlKGNvbG9yID0gJ2JsYWNrJykgKyAKICAgIFBsb3RUaGVtZTMgKwogICAgRGlldGNvbFNjYWxlX2ZpbGwgKyAKICAgIGZhY2V0X2dyaWQocGFpcl9kaWV0c35pbmZfcm91dGUsIHNjYWxlcyA9ICdmcmVlJywgc3BhY2UgPSAnZnJlZScpCgpwcmludChwMSkKCmdnc2F2ZShwMSwKICAgICAgIGZpbGVuYW1lID0gZ2x1ZSgie3drZGlyfS9EVkdfZmlndXJlcy9maW5hbC5zYW1wbGVzLnBkZiIpLAogICAgICAgd2lkdGggPSA2LAogICAgICAgaGVpZ2h0ID0gNiwgbGltaXRzaXplPUZBTFNFLCB1c2VEaW5nYmF0cyA9IEZBTFNFKQoKZ2dzYXZlKHAxLAogICAgICAgZmlsZW5hbWUgPSBnbHVlKCJ7d2tkaXJ9L0RWR19maWd1cmVzL2ZpbmFsLnNhbXBsZXMucG5nIiksCiAgICAgICB3aWR0aCA9IDYsCiAgICAgICBoZWlnaHQgPSA2LCBsaW1pdHNpemU9RkFMU0UpICMsIHVzZURpbmdiYXRzID0gRkFMU0UpCmBgYAoKYGBge3J9CmR2Z19yZXBzID0gZHZnX3JlcHMgJT4lIAogICAgICAgICAgICBmaWx0ZXIoRFZHX2ZyZXEueCA+IGNvdW50X2N1dCAmIERWR19mcmVxLnkgPiBjb3VudF9jdXQpICU+JSAKICAgICAgICB1bmlxdWUoKSAgICMgbWFrZSBzdXJlIHRoYXQgYm90aCByZXBzIHBhc3Mgb3VyIGN1dG9mZgoKIyBhZGQgaW4gdmFyaWFibGVzIGZvciBwbG90dGluZwpkdmdfcmVwcyRmZXJyZXRfZGF5ID0gcGFzdGUwKGR2Z19yZXBzJGZlcnJldF9pZCwgJ18nLCBkdmdfcmVwcyRkcGkpICAKCm0kZmVycmV0X2RheSA9IHBhc3RlMChtJGZlcnJldF9pZCwgJ18nLCBtJGRwaSkKYGBgCgpgYGB7cn0Kc3RvY2tfdGVtcCA9IGR2Z19yZXBzICU+JSBmaWx0ZXIoZHBpID09ICdzdG9jaycpICU+JQogICAgZ3JvdXBfYnkoZmVycmV0X2lkLCBjb2hvcnQsIGRwaSwgc2VnbWVudCwgbmFtZS54LCBuYW1lLnkpICU+JQogICAgYWRkX3RhbGx5KG5hbWUgPSAnc2VnX2RlbGV0aW9uX3JpY2huZXNzJykgJT4lCiAgICB1bmlxdWUoKSAlPiUKICAgIHVuZ3JvdXAoKSAlPiUgCiAgICBncm91cF9ieShmZXJyZXRfaWQsIGRwaSwgbmFtZS54LCBuYW1lLnksIGNvaG9ydCkgJT4lIAogICAgYWRkX3RhbGx5KG5hbWUgPSAnZGVsZXRpb25fcmljaG5lc3MnKSAlPiUKICAgIHVuZ3JvdXAoKSAlPiUgCiAgICB1bmlxdWUoKQoKcyA9IHN0b2NrX3RlbXAgICMgd2lsbCB1c2UgbGF0ZXIKCiMgZmlsdGVyIGRvd24gc3RvY2sgdGVtcCBpbmZvcm1hdGlvbgpzdG9ja190ZW1wID0gc3RvY2tfdGVtcCAlPiUgCiAgICAgICAgICAgIHNlbGVjdChmZXJyZXRfaWQsIGRwaSwgY29ob3J0LGZlcnJldF9kYXksIHNlZ21lbnQsIGRlbGV0aW9uX3JpY2huZXNzLCBzZWdfZGVsZXRpb25fcmljaG5lc3MpICU+JQogICAgICAgICAgICB1bmlxdWUoKQoKCnN0b2NrX3RlbXAgPSBtZXJnZShzdG9ja190ZW1wLCBtLCBieSA9IGMoJ2ZlcnJldF9pZCcsICdkcGknLCdjb2hvcnQnLCdmZXJyZXRfZGF5JykpICU+JSAKICAgIHVuaXF1ZSgpCmBgYAoKYGBge3J9CiMgZmlsdGVyIG91dCBzdG9jayBpbmZvcm1hdGlvbiwgY2FsY3VsYXRlIGR2ZyByaWNobmVzcyBieSBzZWdtZW50IGFuZCBhY3Jvc3MgZ2Vub21lIGZvciBzYW1wbGVzCmRyID0gZHZnX3JlcHMgJT4lIAogICAgICAgICAgICBmaWx0ZXIoZHBpICE9ICdzdG9jaycpICU+JSAKICAgICAgICAgICAgdW5pcXVlKCkgJT4lIAogICAgICAgICAgICBncm91cF9ieShmZXJyZXRfaWQsIGRwaSwgc2VnbWVudCwgbmFtZS54LCBuYW1lLnksIGNvaG9ydCkgJT4lCiAgICAgICAgICAgIGFkZF90YWxseShuYW1lID0gJ3NlZ19kZWxldGlvbl9yaWNobmVzcycpICU+JQogICAgICAgICAgICB1bmdyb3VwKCkgJT4lIAogICAgICAgICAgICBncm91cF9ieShmZXJyZXRfaWQsIGRwaSwgbmFtZS54LCBuYW1lLnksIGNvaG9ydCkgJT4lIAogICAgICAgICAgICBhZGRfdGFsbHkobmFtZSA9ICdkZWxldGlvbl9yaWNobmVzcycpICU+JQogICAgICAgICAgICB1bmdyb3VwKCkgJT4lIAogICAgICAgICAgICB1bmlxdWUoKQoKIyBmaWx0ZXIgZG93biBpbmZvcm1hdGlvbiBzbyB5b3UgZG9uJ3QgaGF2ZSBkdXBsaWNhdGVzCnJpY2huZXNzID0gZHIgJT4lIAogICAgICAgICAgICBzZWxlY3QoZmVycmV0X2lkLCBkcGksIGNvaG9ydCxmZXJyZXRfZGF5LCBzZWdtZW50LCBkZWxldGlvbl9yaWNobmVzcywgc2VnX2RlbGV0aW9uX3JpY2huZXNzKSAlPiUKICAgICAgICAgICAgdW5pcXVlKCkKCiMgbWVyZ2Ugd2l0aCBtZXRhZGF0YSBpbmZvCiNyaWNobmVzcyA9IG1lcmdlKHJpY2huZXNzLCBtLCBieSA9IGMoJ2ZlcnJldF9pZCcsICdkcGknLCdjb2hvcnQnLCdmZXJyZXRfZGF5JyksIGFsbC55ID0gVFJVRSkgJT4lICMgQ0hBTkdFRApyaWNobmVzcyA9IG1lcmdlKHJpY2huZXNzLCBtLCBieSA9IGMoJ2ZlcnJldF9pZCcsICdkcGknLCdjb2hvcnQnLCdmZXJyZXRfZGF5JyksIGFsbC54ID0gVFJVRSkgJT4lCiAgICB1bmlxdWUoKSAlPiUgCiAgZmlsdGVyKCFpcy5uYShpbmZfcm91dGUpKQoKIyBtYWtlIHN1cmUgd2UgZmlsdGVyIG91dCBzdG9jayBpbmZvcm1hdGlvbiAod2lsbCBhZGQgdXNpbmcgdGhlICdzJyBkYXRhZnJhbWUgZ2VuZXJhdGVkIGFib3ZlKQpyaWNobmVzcyA9IHJpY2huZXNzICU+JSBmaWx0ZXIoZHBpICE9ICdzdG9jaycpCgpyZXBzX2RmID0gcmJpbmQoZHIsIHMpICU+JSB1bmlxdWUoKSAjIGZpbmFsIHJlcHMgcmljaG5lc3MgZGYKcmVwc19kZiA9IG1lcmdlKHJlcHNfZGYsIG0sIGJ5ID0gYygnZmVycmV0X2lkJywnZHBpJywnY29ob3J0JywnZmVycmV0X2RheScsJ25hbWUueCcsJ3JlcC54JywnbmFtZS55JywncmVwLnknKSkgICU+JSB1bmlxdWUoKSAjIGFkZCBtZXRhZGF0YQpgYGAKCmBgYHtyfQpwNCA9IHJlcHNfZGYgJT4lIAogICAgc2VsZWN0KHNlZ21lbnQsIE5ld0dhcCwgRXN0aW1hdGVkRnJhZ0xlbmd0aCwgZGlldCkgJT4lCiAgICB1bmlxdWUoKSAlPiUKICAgIGdncGxvdCguLCBhZXMoeD0gRXN0aW1hdGVkRnJhZ0xlbmd0aCkpICsgCiAgICBnZW9tX2hpc3RvZ3JhbShjb2xvciA9ICdibGFjaycpICsgCiAgICBQbG90VGhlbWUxICsKICAgIGxhYnMoeD0iZXN0aW1hdGVkIERWRyBmcmFnLiBsZW5ndGggKG50KSIsIHk9J251bWJlciBvZiB1bmlxdWUgRFZHIHNwZWNpZXMnKSAKcHJpbnQocDQpCgpnZ3NhdmUocDQsCiAgICAgICBmaWxlbmFtZSA9IGdsdWUoInt3a2Rpcn0vRFZHX2ZpZ3VyZXMvZGVsZXRpb24uc2l6ZS5wZGYiKSwKICAgICAgIHdpZHRoID0gNSwKICAgICAgIGhlaWdodCA9IDUsIGxpbWl0c2l6ZT1GQUxTRSwgdXNlRGluZ2JhdHMgPSBGQUxTRSkKCmdnc2F2ZShwNCwKICAgICAgIGZpbGVuYW1lID0gZ2x1ZSgie3drZGlyfS9EVkdfZmlndXJlcy9kZWxldGlvbi5zaXplLnBuZyIpLAogICAgICAgd2lkdGggPTUsCiAgICAgICBoZWlnaHQgPSA1LCBsaW1pdHNpemU9RkFMU0UpICMsIHVzZURpbmdiYXRzID0gRkFMU0UpCgpwNF9hbHQgPSByZXBzX2RmICU+JSAKICAgIHNlbGVjdChzZWdtZW50LCBOZXdHYXAsIEVzdGltYXRlZEZyYWdMZW5ndGgsIGRpZXQsIGluZl9yb3V0ZSkgJT4lCiAgICB1bmlxdWUoKSAlPiUKICAgIGdncGxvdCguLCBhZXMoeD0gRXN0aW1hdGVkRnJhZ0xlbmd0aCkpICsgCiAgICBnZW9tX2hpc3RvZ3JhbShjb2xvciA9ICdibGFjaycsIGJpbndpZHRoID0gNTApICsgCiAgICBmYWNldF9ncmlkKGluZl9yb3V0ZX5kaWV0KSArCiAgICBQbG90VGhlbWUxICsKICAgIGxhYnMoeD0iZXN0aW1hdGVkIERWRyBmcmFnLiBsZW5ndGggKG50KSIsIHk9J251bWJlciBvZiB1bmlxdWUgRFZHIHNwZWNpZXMnKSAKcHJpbnQocDRfYWx0KQpnZ3NhdmUocDRfYWx0LAogICAgICAgZmlsZW5hbWUgPSBnbHVlKCJ7d2tkaXJ9L0RWR19maWd1cmVzL2RlbGV0aW9uLnNpemUuYnlkaWV0LmJ5dHlwZS5wZGYiKSwKICAgICAgIHdpZHRoID0gMTAsCiAgICAgICBoZWlnaHQgPSA1LCBsaW1pdHNpemU9RkFMU0UsIHVzZURpbmdiYXRzID0gRkFMU0UpCgpgYGAKCmBgYHtyfQpsZWFuX2luZGV4ID0gIHJlcHNfZGYgJT4lIGZpbHRlcihpbmZfcm91dGUgPT0gJ0luZGV4JyAmIGRpZXQgPT0gJ0xlYW4nKSAlPiUgCiAgICAgICAgICAgICAgICB1bmlxdWUoKSAlPiUKICAgICAgICAgICAgICAgIGdyb3VwX2J5KE5ld0dhcCwgc2VnbWVudCwgTmV3U3RhcnQsIE5ld0VuZCkgJT4lCiAgICAgICAgICAgIGFkZF90YWxseShuYW1lID0gJ2xlYW5fZGVsZXRpb25fY291bnQnKSAlPiUKICAgIHVuZ3JvdXAoKSAlPiUKICAgIHNlbGVjdChOZXdHYXAsIHNlZ21lbnQsIGxlYW5fZGVsZXRpb25fY291bnQpICU+JQogICAgdW5pcXVlKCkKCgpvYmVzZV9pbmRleCA9ICByZXBzX2RmICU+JSBmaWx0ZXIoaW5mX3JvdXRlID09ICdJbmRleCcgJiBkaWV0ID09ICdPYmVzZScpICU+JSAKICAgICAgICAgICAgICAgIHVuaXF1ZSgpICU+JQogICAgICAgICAgICAgICAgZ3JvdXBfYnkoTmV3R2FwLCBzZWdtZW50LCBOZXdTdGFydCwgTmV3RW5kKSAlPiUKICAgICAgICAgICAgYWRkX3RhbGx5KG5hbWUgPSAnb2Jlc2VfZGVsZXRpb25fY291bnQnKSAlPiUKICAgIHVuZ3JvdXAoKSAlPiUKICAgIHNlbGVjdChOZXdHYXAsIHNlZ21lbnQsIG9iZXNlX2RlbGV0aW9uX2NvdW50KSAlPiUKICAgIHVuaXF1ZSgpCgoKZGYgPSBtZXJnZShsZWFuX2luZGV4LCBvYmVzZV9pbmRleCwgYnkgPSBjKCdOZXdHYXAnLCdzZWdtZW50JyksIGFsbCA9IFRSVUUpIAoKaGVhZChkZikKCmRmJGxlYW5fZGVsZXRpb25fY291bnRbaXMubmEoZGYkbGVhbl9kZWxldGlvbl9jb3VudCldID0gMAoKZGYkb2Jlc2VfZGVsZXRpb25fY291bnRbaXMubmEoZGYkb2Jlc2VfZGVsZXRpb25fY291bnQpXSA9IDAKYGBgCgpgYGB7cn0KcDggPSByZXBzX2RmICU+JSBmaWx0ZXIoaW5mX3JvdXRlID09ICdJbmRleCcpICU+JSAKICAgICAgICAgICAgICAgIHVuaXF1ZSgpICU+JQogICAgICAgICAgICAgICAgZ3JvdXBfYnkoTmV3R2FwLCBzZWdtZW50LCBOZXdTdGFydCwgTmV3RW5kKSAlPiUKICAgICAgICAgICAgYWRkX3RhbGx5KG5hbWUgPSAnc2FtcGxlX2NvdW50JykgJT4lCiAgICB1bmdyb3VwKCkgJT4lCiAgICBzZWxlY3QoTmV3R2FwLCBzZWdtZW50LHNhbXBsZV9jb3VudCkgJT4lCiAgICB1bmlxdWUoKSAgJT4lCiAgICBnZ3Bsb3QoLiwgYWVzKHg9c2FtcGxlX2NvdW50LCB5ID0gLi5jb3VudC4uL3N1bSguLmNvdW50Li4pKSkgKwogICAgZ2VvbV9oaXN0b2dyYW0oY29sb3IgPSdibGFjaycpICsgCiAgICBsYWJzKHg9J251bWJlciBvZiBzYW1wbGVzIHdpdGggRFZHIHR5cGUnLCB5PSdwcm9wb3J0aW9uIG9mIERWR3MgaW4gZGF0YXNldCAoaW5kZXggb25seSknKSArIAogICAgUGxvdFRoZW1lMSAKCnByaW50KHA4KQpnZ3NhdmUocDgsCiAgICAgICBmaWxlbmFtZSA9IGdsdWUoInt3a2Rpcn0vRFZHX2ZpZ3VyZXMvc2FtcGxlLmNvdW50Lmhpc3RvLnBkZiIpLAogICAgICAgd2lkdGggPSA1LAogICAgICAgaGVpZ2h0ID0gNSwgbGltaXRzaXplPUZBTFNFLCB1c2VEaW5nYmF0cyA9IEZBTFNFKQoKZ2dzYXZlKHA4LAogICAgICAgZmlsZW5hbWUgPSBnbHVlKCJ7d2tkaXJ9L0RWR19maWd1cmVzL3NhbXBsZS5jb3VudC5oaXN0by5wbmciKSwKICAgICAgIHdpZHRoID01LAogICAgICAgaGVpZ2h0ID0gNSwgbGltaXRzaXplPUZBTFNFKSAjLCB1c2VEaW5nYmF0cyA9IEZBTFNFKQpgYGAKCmBgYHtyfQpyZXBzX2RmJGF2ZV9kdmdfZnJlcSA9IChyZXBzX2RmJERWR19mcmVxLnggKyByZXBzX2RmJERWR19mcmVxLnkpLzIKYGBgCgpgYGB7cn0KcmVwc19kZiA9IHJlcHNfZGYgJT4lCiAgZHBseXI6OmFycmFuZ2UoZmVycmV0X2RheSwgYXZlX2R2Z19mcmVxKSAlPiUgCiAgZHBseXI6Omdyb3VwX2J5KGZlcnJldF9kYXkpICU+JSAKICBkcGx5cjo6bXV0YXRlKG9yZGVyX251bWJlciA9IHJvd19udW1iZXIoKSkgJT4lIAogIHVuZ3JvdXAoKSAlPiUKICB1bmlxdWUoKQpgYGAKCmBgYHtyfQpyZXBzX2RmICU+JSAKICAgIGRwbHlyOjpncm91cF9ieShOZXdHYXAsIHNlZ21lbnQsIGluZl9yb3V0ZSwgZGlldCkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKG1lYW5fb3JkZXIgPSBtZWFuKG9yZGVyX251bWJlciksCiAgICAgICAgICBzYW1wbGVfY291bnQgPSBuKCksCiAgICAgICAgICBtaW5fb3JkZXIgPSBtaW4ob3JkZXJfbnVtYmVyKSwKICAgICAgICAgIG1heF9vcmRlciA9IG1heChvcmRlcl9udW1iZXIpLAogICAgICAgICAgbWVkaWFuX29yZCA9IG1lZGlhbihvcmRlcl9udW1iZXIpKSAlPiUKICAgIHVuZ3JvdXAoKSAlPiUKICAgIHVuaXF1ZSgpICU+JQogICAgc2VsZWN0KHNlZ21lbnQsIE5ld0dhcCwgbWVhbl9vcmRlciwgc2FtcGxlX2NvdW50LCBtaW5fb3JkZXIsIG1heF9vcmRlciwgbWVkaWFuX29yZCwgaW5mX3JvdXRlLCBkaWV0KSAlPiUKICAgIGZpbHRlcihzYW1wbGVfY291bnQgPiAxKSAlPiUKICAgIHVuaXF1ZSgpICU+JQogICAgZ2dwbG90KC4sIGFlcyh5PW1lYW5fb3JkZXIsIHggPSBzYW1wbGVfY291bnQpKSArIAogICAgZ2VvbV9wb2ludCgpICsgCiAgICBQbG90VGhlbWUxICsgCiAgICBmYWNldF9ncmlkKC5+ZGlldCArIGluZl9yb3V0ZSkKYGBgCgpgYGB7cn0KdG9wX3RlbiA9IHJlcHNfZGYgJT4lIGZpbHRlcihvcmRlcl9udW1iZXIgJWluJSBjKDEsIDIsMyAsNCwgNSwgNiwgNywgOCwgOSwgMTApKSAlPiUgdW5pcXVlKCkKCmhlYWQodG9wX3RlbikKCmxlbmd0aChsZXZlbHMoZmFjdG9yKHRvcF90ZW4kTmV3R2FwKSkpCmBgYAoKYGBge3J9Cm1heChkZiRsZWFuX2RlbGV0aW9uX2NvdW50KQptYXgoZGYkb2Jlc2VfZGVsZXRpb25fY291bnQpCgpwOSA9IGdncGxvdChkZiwgYWVzKHg9bGVhbl9kZWxldGlvbl9jb3VudCwgeSA9IG9iZXNlX2RlbGV0aW9uX2NvdW50KSkgKyAKICAgIGdlb21faml0dGVyKHdpZHRoID0gMC4xLCBoZWlnaHQgPSAwLjEsIGFscGhhID0gMC4zKSArIAogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAyLCBjb2xvciA9ICdibGFjaycpICsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDI1LCBsaW5ldHlwZSA9IDIsIGNvbG9yID0gJ3JlZCcpICsKICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gMiwgY29sb3IgPSAnYmxhY2snKSArCiAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAxNywgbGluZXR5cGUgPSAyLCBjb2xvciA9ICdyZWQnKSArCiAgICBsYWJzKHg9ICdudW1iZXIgb2YgbGVhbiBzYW1wbGVzIHdpdGggRFZHJywgeT0nbnVtYmVyIG9mIG9iZXNlIHNhbXBsZXMgd2l0aCBEVkcnKSArIAogICAgUGxvdFRoZW1lMSAKCnByaW50KHA5KQpnZ3NhdmUocDksCiAgICAgICBmaWxlbmFtZSA9IGdsdWUoInt3a2Rpcn0vRFZHX2ZpZ3VyZXMvc2FtcGxlLmNvdW50LmxlYW4udi5vYmVzZS5wZGYiKSwKICAgICAgIHdpZHRoID0gNSwKICAgICAgIGhlaWdodCA9IDUsIGxpbWl0c2l6ZT1GQUxTRSwgdXNlRGluZ2JhdHMgPSBGQUxTRSkKCmdnc2F2ZShwOSwKICAgICAgIGZpbGVuYW1lID0gZ2x1ZSgie3drZGlyfS9EVkdfZmlndXJlcy9zYW1wbGUuY291bnQubGVhbi52Lm9iZXNlLnBuZyIpLAogICAgICAgd2lkdGggPTUsCiAgICAgICBoZWlnaHQgPSA1LCBsaW1pdHNpemU9RkFMU0UpICMsIHVzZURpbmdiYXRzID0gRkFMU0UpCmBgYAoKYGBge3J9CnJpY2huZXNzID0gcmJpbmQocmljaG5lc3MsIHN0b2NrX3RlbXApCiNyaWNobmVzcyRkZWxldGlvbl9yaWNobmVzc1tpcy5uYShyaWNobmVzcyRkZWxldGlvbl9yaWNobmVzcyldID0gMAoKREFZUyA9IGMoJ3N0b2NrJywnZDAyJywnZDA0JywnZDA2JywnZDA4JywnZDEwJywnZDEyJykKYGBgCgpgYGB7cn0KcmljaG5lc3MkZHBpID0gZmFjdG9yKHJpY2huZXNzJGRwaSwgbGV2ZWxzID0gREFZUykKcmljaG5lc3MgJT4lIGZpbHRlcihkcGkgJWluJSBjKCdkMDInLCdkMDQnKSkgJT4lCiAgICAgICAgZmlsdGVyKGluZl9yb3V0ZSA9PSAnSW5kZXgnIHwgaW5mX3JvdXRlID09ICdDb250cm9sJykgJT4lCiAgICAgICAgZmlsdGVyKCEoaXMubmEoaW5mX3JvdXRlKSkpICU+JQogICAgc2VsZWN0KGZlcnJldF9pZCwgZHBpLCBkZWxldGlvbl9yaWNobmVzcywgaW5mX3JvdXRlLCBkaWV0LCBwYWlyX2RpZXRzLCBjb2hvcnQpICU+JQogICAgdW5pcXVlKCkgJT4lCiAgICBncm91cF9ieShmZXJyZXRfaWQpICU+JQogICAgYWRkX3RhbGx5KG5hbWUgPSAnbicpICU+JQogICAgdW5ncm91cCgpICU+JQogICAgZmlsdGVyKG4gPj0gMikgJT4lIAogICAgdW5ncm91cCgpICU+JQogICAgdW5pcXVlKCkgJT4lCiAgICBnZ3Bsb3QoLiwgYWVzKHg9ZHBpLCB5ID0gZGVsZXRpb25fcmljaG5lc3MsIGNvbG9yID0gY29ob3J0LCBncm91cD1mZXJyZXRfaWQsIHNoYXBlID0gZGlldCkpICsgCiAgICAjZ2VvbV9ib3hwbG90KCkgKyAKICAgIGdlb21fbGluZSgpICsgCiAgICBnZW9tX3BvaW50KHNpemUgPSAyKSArIAogICAgUGxvdFRoZW1lMSArCiAgICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZSA9ICdTZXQxJykKICAgICNEaWV0Y29sU2NhbGUgKyAKICAgICNmYWNldF9ncmlkKC5+Y29ob3J0KQoKCnA3ID0gcmljaG5lc3MgJT4lIGZpbHRlcihkcGkgJWluJSBjKCdkMDInLCdkMDQnLCdkMDYnKSkgJT4lCiAgICAgICAgZmlsdGVyKGluZl9yb3V0ZSA9PSAnSW5kZXgnIHwgaW5mX3JvdXRlID09ICdDb250cm9sJykgJT4lICAgIAogICAgc2VsZWN0KGZlcnJldF9pZCwgZHBpLCBkZWxldGlvbl9yaWNobmVzcywgaW5mX3JvdXRlLCBkaWV0LCBwYWlyX2RpZXRzLCBjb2hvcnQpICU+JQogICAgdW5pcXVlKCkgJT4lCiAgICBncm91cF9ieShmZXJyZXRfaWQpICU+JQogICAgYWRkX3RhbGx5KG5hbWUgPSAnbicpICU+JQogICAgdW5ncm91cCgpICU+JQogICAgZmlsdGVyKG4gPj0gMikgJT4lIAogICAgdW5ncm91cCgpICU+JQogICAgdW5pcXVlKCkgJT4lCiAgICBnZ3Bsb3QoLiwgYWVzKHg9ZHBpLCB5ID0gZGVsZXRpb25fcmljaG5lc3MsIGNvbG9yID0gZGlldCwgZ3JvdXA9ZmVycmV0X2lkLCBzaGFwZSA9IGRpZXQpKSArIAogICAgI2dlb21fYm94cGxvdCgpICsgCiAgICBnZW9tX2xpbmUoKSArIAogICAgZ2VvbV9wb2ludChzaXplID0gMikgKyAKICAgIFBsb3RUaGVtZTEgKwogICAgRGlldGNvbFNjYWxlCiAgICAjZmFjZXRfZ3JpZCgufmNvaG9ydCkKCnByaW50KHA3KQpnZ3NhdmUocDcsCiAgICAgICBmaWxlbmFtZSA9IGdsdWUoInt3a2Rpcn0vRFZHX2ZpZ3VyZXMvcmljaG5lc3MuaW5kZXgucGRmIiksCiAgICAgICB3aWR0aCA9IDUsCiAgICAgICBoZWlnaHQgPSA1LCBsaW1pdHNpemU9RkFMU0UsIHVzZURpbmdiYXRzID0gRkFMU0UpCgpnZ3NhdmUocDcsCiAgICAgICBmaWxlbmFtZSA9IGdsdWUoInt3a2Rpcn0vRFZHX2ZpZ3VyZXMvcmljaG5lc3MuaW5kZXgucG5nIiksCiAgICAgICB3aWR0aCA9NSwKICAgICAgIGhlaWdodCA9IDUsIGxpbWl0c2l6ZT1GQUxTRSkgIywgdXNlRGluZ2JhdHMgPSBGQUxTRSkKYGBgCgpgYGB7cn0KY29sbmFtZXMocmljaG5lc3MpCm9yZGVyX3R5cGVkYXkgPSBjKCdDb250cm9sX3N0b2NrJywKICAgICAgICAgICAgICAgICAgJ0luZGV4X2QwMicsJ0luZGV4X2QwNCcsJ0luZGV4X2QwNicsJ0luZGV4X2QwOCcsJ0luZGV4X2QxMCcsJ0luZGV4X2QxMicsCiAgICAgICAgICAgICAgICAgICdDb250YWN0X2QwMicsJ0NvbnRhY3RfZDA0JywnQ29udGFjdF9kMDYnLCdDb250YWN0X2QwOCcsJ0NvbnRhY3RfZDEwJywnQ29udGFjdF9kMTInKQpgYGAKCmBgYHtyfQpyaWNobmVzcyR0eXBlX2RheSA9IHBhc3RlMChyaWNobmVzcyRpbmZfcm91dGUsICdfJywgcmljaG5lc3MkZHBpKQpyaWNobmVzcyR0eXBlX2RheSA9IGZhY3RvcihyaWNobmVzcyR0eXBlX2RheSwgbGV2ZWxzID0gb3JkZXJfdHlwZWRheSkKCnAyID0gcmljaG5lc3MgJT4lIGZpbHRlcihkaWV0ID09ICdPYmVzZScgJiBwYWlyX2RpZXRzID09ICdPQj5PQicpICU+JQogICAgc2VsZWN0KGZlcnJldF9pZCwgZHBpLCBkZWxldGlvbl9yaWNobmVzcywgaW5mX3JvdXRlLCBkaWV0LCBwYWlyX251bWJlcnMsIHBhaXJfZGlldHMsIHR5cGVfZGF5KSAlPiUKICAgIHVuZ3JvdXAoKSAlPiUKICAgIHVuaXF1ZSgpICU+JQogICAgZ2dwbG90KC4sIGFlcyh4PXR5cGVfZGF5LCB5ID0gZGVsZXRpb25fcmljaG5lc3MsIGNvbG9yID0gcGFpcl9udW1iZXJzLCBncm91cD1wYWlyX251bWJlcnMpKSArIAogICAgI2dlb21fYm94cGxvdCgpICsgCiAgICBnZW9tX2xpbmUoc2l6ZSA9IDEpICsgCiAgICBnZW9tX3BvaW50KHNpemUgPSAyKSArIAogICAgbGFicyh4PSdkcGkgKGJ5IGluZGV4IGNhc2UpJywgeT0nRFZHIHJpY2huZXNzJykgKyAKICAgIFBsb3RUaGVtZTEgKwogICAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAnU2V0MicpICMrCiAgICAjRGlldGNvbFNjYWxlICsgCiAgICAjZmFjZXRfZ3JpZCgufmluZl9yb3V0ZSkKCnByaW50KHAyKQpnZ3NhdmUocDIsCiAgICAgICBmaWxlbmFtZSA9IGdsdWUoInt3a2Rpcn0vRFZHX2ZpZ3VyZXMvb2Jlc2UudG8ub2Jlc2UuZGl2ZXJzaXR5LnBkZiIpLAogICAgICAgd2lkdGggPSA4LAogICAgICAgaGVpZ2h0ID0gNiwgbGltaXRzaXplPUZBTFNFLCB1c2VEaW5nYmF0cyA9IEZBTFNFKQoKZ2dzYXZlKHAyLAogICAgICAgZmlsZW5hbWUgPSBnbHVlKCJ7d2tkaXJ9L0RWR19maWd1cmVzL29iZXNlLnRvLm9iZXNlLmRpdmVyc2l0eS5wbmciKSwKICAgICAgIHdpZHRoID04LAogICAgICAgaGVpZ2h0ID0gNiwgbGltaXRzaXplPUZBTFNFKSAjLCB1c2VEaW5nYmF0cyA9IEZBTFNFKQpgYGAKCmBgYHtyfQpnZW5fcmljaCA9IHJpY2huZXNzICU+JSAKICBzZWxlY3QoZmVycmV0X2lkLCBkcGksIGNvaG9ydCxkZWxldGlvbl9yaWNobmVzcywgaW5mX3JvdXRlLCBkaWV0LCBwYWlyX251bWJlcnMsIHBhaXJfZGlldHMsIHR5cGVfZGF5KSAlPiUKICB1bmlxdWUoKQoKaGVhZChnZW5fcmljaCkKCmdlbl9yaWNoICU+JSBmaWx0ZXIoZHBpICVpbiUgYygnZDAyJywnZDA0JywnZDA2Jywnc3RvY2snKSkgJT4lCiAgICBmaWx0ZXIoaW5mX3JvdXRlID09ICdJbmRleCcgfCBpbmZfcm91dGUgPT0gIkNvbnRyb2wiKSAlPiUKICAgIGdncGxvdCguLCBhZXMoeD1kaWV0LCB5ID0gZGVsZXRpb25fcmljaG5lc3MsIGdyb3VwID0gZGlldCkpICsgCiAgICBnZW9tX2JveHBsb3Qob3V0bGllci5zaGFwZSA9IE5BKSArIAogICAgZ2VvbV9qaXR0ZXIod2lkdGggPSAwLjIsIGFlcyhjb2xvciA9IGRpZXQpKSArCiAgICBsYWJzKHg9J3NlZ21lbnQnLHk9J2RlbGV0aW9uIHJpY2huZXNzJykgKyAKICAgIFBsb3RUaGVtZTEgKwogICAgRGlldGNvbFNjYWxlICsKICAgIGZhY2V0X2dyaWQoLn5kcGkpCmBgYAoKVGVzdCBmb3Igc2lnbmlmaWNhbmNlCmBgYHtyfQpvID0gZmlsdGVyKGdlbl9yaWNoLCBpbmZfcm91dGUgPT0gIkluZGV4IiAmIGRwaSA9PSAiZDA2IiAmIGRpZXQgPT0gIk9iZXNlIikKbCA9IGZpbHRlcihnZW5fcmljaCwgaW5mX3JvdXRlID09ICJJbmRleCIgJiBkcGkgPT0gImQwNiIgJiBkaWV0ID09ICJMZWFuIikKdC50ZXN0KG8kZGVsZXRpb25fcmljaG5lc3MsbCRkZWxldGlvbl9yaWNobmVzcykKYGBgCgpgYGB7cn0Kc2VnX3JpY2ggPSByaWNobmVzcyAlPiUgI2ZpbHRlcihkaWV0ID09ICdvYmVzZScgJiBwYWlyX2RpZXRzID09ICdvYmVzZV9vYmVzZScpICU+JQogICAgc2VsZWN0KGZlcnJldF9pZCwgZHBpLCBzZWdfZGVsZXRpb25fcmljaG5lc3MsIGluZl9yb3V0ZSwgZGlldCwgCiAgICAgICAgICAgcGFpcl9udW1iZXJzLCBwYWlyX2RpZXRzLCB0eXBlX2RheSwgc2VnbWVudCkgJT4lCiAgICB1bmlxdWUoKQoKaGVhZChzZWdfcmljaCkKCnRlbXAgPSBzZWdfcmljaCAlPiUgc2VsZWN0KGZlcnJldF9pZCwgZHBpLCBpbmZfcm91dGUsIGRpZXQsIHBhaXJfbnVtYmVycywgdHlwZV9kYXksIHBhaXJfZGlldHMpICU+JSB1bmlxdWUoKQp0ZW1wJEg5TjJfUEIyID0gMAp0ZW1wJEg5TjJfUEIxID0gMAp0ZW1wJEg5TjJfUEEgPSAwCnRlbXAkSDlOMl9IQSA9IDAKdGVtcCRIOU4yX05QID0gMAp0ZW1wJEg5TjJfTkEgPSAwCnRlbXAkSDlOMl9NUCA9IDAKdGVtcCRIOU4yX05TID0gMAoKdGVtcCA9IHBpdm90X2xvbmdlcih0ZW1wLCBjb2xzID0gYWxsX29mKFNFR01FTlRTKSwgbmFtZXNfdG8gPSAnc2VnbWVudCcpICU+JSBzZWxlY3QoLXZhbHVlKQoKc2VnX3JpY2ggPSBtZXJnZShzZWdfcmljaCwgdGVtcCwgYnkgPSBjKCdmZXJyZXRfaWQnLCAnZHBpJywgJ2luZl9yb3V0ZScsICdkaWV0JywgJ3BhaXJfbnVtYmVycycsICdwYWlyX2RpZXRzJywgJ3R5cGVfZGF5JywgJ3NlZ21lbnQnKSwgYWxsID0gVFJVRSkgCnNlZ19yaWNoJHNlZ19kZWxldGlvbl9yaWNobmVzc1tpcy5uYShzZWdfcmljaCRzZWdfZGVsZXRpb25fcmljaG5lc3MpXSA9IDAKCnNlZ19yaWNoJHNlZ21lbnQgPSBmYWN0b3Ioc2VnX3JpY2gkc2VnbWVudCwgbGV2ZWxzID0gU0VHTUVOVFMpCmhlYWQoc2VnX3JpY2gpCmBgYAoKYGBge3J9CnNlZ19yaWNoICU+JSBmaWx0ZXIoZmVycmV0X2lkID09IDE3ODcpICU+JSBoZWFkKCkKcmljaG5lc3MgJT4lIGZpbHRlcihmZXJyZXRfaWQgPT0gMTc4NykgJT4lIGhlYWQoKQp0ZW1wICU+JSBmaWx0ZXIoZmVycmV0X2lkID09IDE3ODcpCgpgYGAKCmBgYHtyfQpwMyA9IHNlZ19yaWNoICU+JSBmaWx0ZXIoc2VnbWVudCAlaW4lIFNFR01FTlRTKSAlPiUKICAgIGdncGxvdCguLCBhZXMoeD1zZWdtZW50LCB5ID0gc2VnX2RlbGV0aW9uX3JpY2huZXNzKSkgKyAKICAgIGdlb21fYm94cGxvdCgpICsgCiAgICBsYWJzKHg9J3NlZ21lbnQnLHk9J2RlbGV0aW9uIHJpY2huZXNzJykgKyAKICAgIFBsb3RUaGVtZTEgCgpwcmludChwMykKCmdnc2F2ZShwMywKICAgICAgIGZpbGVuYW1lID0gZ2x1ZSgie3drZGlyfS9EVkdfZmlndXJlcy9zZWdtZW50LnJpY2huZXNzLnBkZiIpLAogICAgICAgd2lkdGggPSA1LAogICAgICAgaGVpZ2h0ID0gNSwgbGltaXRzaXplPUZBTFNFLCB1c2VEaW5nYmF0cyA9IEZBTFNFKQoKZ2dzYXZlKHAzLAogICAgICAgZmlsZW5hbWUgPSBnbHVlKCJ7d2tkaXJ9L0RWR19maWd1cmVzL3NlZ21lbnQucmljaG5lc3MucG5nIiksCiAgICAgICB3aWR0aCA9NSwKICAgICAgIGhlaWdodCA9IDUsIGxpbWl0c2l6ZT1GQUxTRSkgIywgdXNlRGluZ2JhdHMgPSBGQUxTRSkKYGBgCgpgYGB7cn0Kc2VnX3JpY2gkc2VnX3dlaWdodCA9IHBhc3RlMChzZWdfcmljaCRzZWdtZW50LCAnXycsIHNlZ19yaWNoJGRpZXQpCnNlZ19yaWNoJGRpZXQgPSBmYWN0b3Ioc2VnX3JpY2gkZGlldCwgbGV2ZWxzID0gYygnQ29udHJvbCcsJ0xlYW4nLCdPYmVzZScpKQpgYGAKCmBgYHtyfQpzZWdfcmljaCAlPiUgZmlsdGVyKHNlZ21lbnQgJWluJSBTRUdNRU5UUykgJT4lCiAgICBkcm9wX25hKGluZl9yb3V0ZSkgJT4lIAogICAgZ2dwbG90KC4sIGFlcyh4PXNlZ21lbnQsIHkgPSBzZWdfZGVsZXRpb25fcmljaG5lc3MsIGdyb3VwID0gc2VnX3dlaWdodCwgY29sb3IgPSBkaWV0KSkgKyAKICAgIGdlb21fYm94cGxvdCgpICsgCiAgICBsYWJzKHg9J3NlZ21lbnQnLHk9J2RlbGV0aW9uIHJpY2huZXNzJykgKyAKICAgIFBsb3RUaGVtZTEgKwogICAgRGlldGNvbFNjYWxlICsKICAgIGZhY2V0X2dyaWQoLn5pbmZfcm91dGUpCgoKcDYgPSBzZWdfcmljaCAlPiUgZmlsdGVyKHNlZ21lbnQgJWluJSBTRUdNRU5UUyAmIGRwaSAlaW4lIGMoJ2QwMicsJ2QwNCcsJ2QwNicpKSAlPiUKICAgIGZpbHRlcihpbmZfcm91dGUgPT0gJ0luZGV4JyB8IGluZl9yb3V0ZSA9PSAiQ29udHJvbCIpICU+JQogICAgZ2dwbG90KC4sIGFlcyh4PXNlZ21lbnQsIHkgPSBzZWdfZGVsZXRpb25fcmljaG5lc3MsIGdyb3VwID0gc2VnX3dlaWdodCwgY29sb3IgPSBkaWV0KSkgKyAKICAgIGdlb21fYm94cGxvdChvdXRsaWVyLnNoYXBlID0gTkEpICsgCiAgICBsYWJzKHg9J3NlZ21lbnQnLHk9J2RlbGV0aW9uIHJpY2huZXNzJykgKyAKICAgIFBsb3RUaGVtZTEgKwogICAgRGlldGNvbFNjYWxlICsKICAgIGZhY2V0X2dyaWQoLn5kcGkpCgpwcmludChwNikKCmdnc2F2ZShwNiwKICAgICAgIGZpbGVuYW1lID0gZ2x1ZSgie3drZGlyfS9EVkdfZmlndXJlcy9zZWdtZW50LmluZGV4LnJpY2huZXNzLnBkZiIpLAogICAgICAgd2lkdGggPSA4LAogICAgICAgaGVpZ2h0ID0gNCwgbGltaXRzaXplPUZBTFNFLCB1c2VEaW5nYmF0cyA9IEZBTFNFKQoKZ2dzYXZlKHA2LAogICAgICAgZmlsZW5hbWUgPSBnbHVlKCJ7d2tkaXJ9L0RWR19maWd1cmVzL3NlZ21lbnQuaW5kZXgucmljaG5lc3MucG5nIiksCiAgICAgICB3aWR0aCA9OCwKICAgICAgIGhlaWdodCA9IDQsIGxpbWl0c2l6ZT1GQUxTRSkgIywgdXNlRGluZ2JhdHMgPSBGQUxTRSkKYGBgCgojIElHTk9SRSBUSElTIFNFQ1RJT04gLSB3aGF0IGl0IGxvb2tlZCBsaWtlIGJlZm9yZSBmZXJyZXQgZGlldHMgd2VyZSBjb3JyZWN0ZWQKYGBge3J9CiMgMTk3MywgMTk3NywgYW5kIDE5ODYgYXJlIGxpc3RlZCBhcyBvYmVzZSB3aGVuIHRoZXkgYXJlIGFjdHVhbGx5IGxlYW4sIGFuZCAxOTg0IGlzIGxpc3RlZCBhcyBsZWFuIHdoZW4gaXQgaXMgYWN0dWFsbHkgb2Jlc2UKCiNzZWdfcmljaCAlPiUgCiAgICAjZmlsdGVyKCFpbmZfcm91dGUgJWluJSBjKCdzdG9jaycsJ2xlYW4nLCdvYmVzZScpKSAlPiUgCiMgICAgZHJvcF9uYShpbmZfcm91dGUpICU+JQojICAgIGZpbHRlcihmZXJyZXRfaWQgPT0gMTQwOCkKCiNvbGRfb2Jlc2UgPSBmaWx0ZXIoc2VnX3JpY2gsIGZlcnJldF9pZCAlaW4lIGMoMTk3MywgMTk3NywgMTk4NikpICU+JSB1bmlxdWUoKQojb2xkX29iZXNlJGRpZXQgPSAiT2Jlc2UiCiNvbGRfbGVhbiA9IGZpbHRlcihzZWdfcmljaCxmZXJyZXRfaWQgPT0gMTk4NCkgJT4lIHVuaXF1ZSgpCiNvbGRfbGVhbiRkaWV0ID0gIkxlYW4iCiNvbGRfc2FtZSA9IGZpbHRlcihzZWdfcmljaCwgZmVycmV0X2lkICE9IGMoMTk3MywgMTk3NywgMTk4NiwgMTk4NCkpCgojZGVsZXRlaXQgPSByYmluZChvbGRfb2Jlc2Usb2xkX2xlYW4sb2xkX3NhbWUpCgojZGVsZXRlaXQgJT4lIGZpbHRlcighZmVycmV0X2lkICVpbiUgYygxOTczLCAxOTc3LDE5ODYsIDE5ODQpICYKIyAgICAgICAgICAgICAgICAgICAgICBzZWdtZW50ICVpbiUgU0VHTUVOVFMgJiBkcGkgJWluJSBjKCdkMDInLCdkMDQnLCdkMDYnLCdzdG9jaycpKSAlPiUKIyAgICBkcm9wX25hKGluZl9yb3V0ZSkgJT4lCiMgICAgZmlsdGVyKGluZl9yb3V0ZSA9PSAnSW5kZXgnIHwgaW5mX3JvdXRlID09ICJDb250cm9sIikgJT4lCiMgICAgZ2dwbG90KC4sIGFlcyh4PXNlZ21lbnQsIHkgPSBzZWdfZGVsZXRpb25fcmljaG5lc3MsIGdyb3VwID0gc2VnX3dlaWdodCwgY29sb3IgPSBkaWV0KSkgKyAKIyAgICBnZW9tX2JveHBsb3Qob3V0bGllci5zaGFwZSA9IE5BKSArIAojICAgIGxhYnMoeD0nc2VnbWVudCcseT0nZGVsZXRpb24gcmljaG5lc3MnKSArIAojICAgIFBsb3RUaGVtZTEgKwojICAgIERpZXRjb2xTY2FsZSArCiMgICAgZmFjZXRfZ3JpZCgufmRwaSkKCiNzZWdfcmljaCAlPiUgZmlsdGVyKGZlcnJldF9pZCAlaW4lIGMoMTk3MywgMTk3NywxOTg2LCAxOTg0KSAmIGRwaSA9PSAnZDA2JykgJT4lIAojICBzZWxlY3QoZmVycmV0X2lkLCBzZWdtZW50LCBkcGksIHNlZ19kZWxldGlvbl9yaWNobmVzcykgCmBgYApUZXN0IGZvciBzaWduaWZpY2FuY2UKYGBge3J9Cm8gPSBmaWx0ZXIoc2VnX3JpY2gsIGluZl9yb3V0ZSA9PSAiSW5kZXgiICYgZHBpID09ICJkMDYiICYgc2VnbWVudCA9PSAiSDlOMl9OUyIgJiBkaWV0ID09ICJPYmVzZSIpCmwgPSBmaWx0ZXIoc2VnX3JpY2gsIGluZl9yb3V0ZSA9PSAiSW5kZXgiICYgZHBpID09ICJkMDYiICYgc2VnbWVudCA9PSAiSDlOMl9OUyIgJiBkaWV0ID09ICJMZWFuIikKdC50ZXN0KG8kc2VnX2RlbGV0aW9uX3JpY2huZXNzLGwkc2VnX2RlbGV0aW9uX3JpY2huZXNzKQojIFNpZ25pZmljYW5jZTogbm9uZQpgYGAKCmBgYHtyfQpzZWdfcmljaCAlPiUgZmlsdGVyKGluZl9yb3V0ZSA9PSAnSW5kZXgnICYgIHNlZ21lbnQgJWluJSBTRUdNRU5UUykgJT4lCiAgICB1bmdyb3VwKCkgJT4lCiAgICB1bmlxdWUoKSAlPiUKICAgIGdncGxvdCguLCBhZXMoeD10eXBlX2RheSwgeSA9IHNlZ19kZWxldGlvbl9yaWNobmVzcywgY29sb3IgPSBzZWdtZW50LCBncm91cD1zZWdtZW50KSkgKyAKICAgICNnZW9tX2JveHBsb3QoKSArIAogICAgZ2VvbV9saW5lKHNpemUgPSAxKSArIAogICAgZ2VvbV9wb2ludChzaXplID0gMikgKyAKICAgIGxhYnMoeD0nZHBpIChieSBpbmRleCBjYXNlKScsIHk9J0RWRyByaWNobmVzcycpICsgCiAgICBQbG90VGhlbWUxICsKICAgIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gJ1NldDInKSArCiAgICAjRGlldGNvbFNjYWxlICsgCiAgICBmYWNldF9ncmlkKC5+ZGlldCArIGZlcnJldF9pZCwgc2NhbGVzID0gJ2ZyZWUnLCBzcGFjZSA9ICdmcmVlJykKYGBgCgpgYGB7cn0KcDQgPSBzZWdfcmljaCAlPiUgZmlsdGVyKGRpZXQgPT0gJ09iZXNlJyAmIHBhaXJfZGlldHMgPT0gJ09CPk9CJyAmIHNlZ21lbnQgJWluJSBTRUdNRU5UUykgJT4lCiAgICB1bmdyb3VwKCkgJT4lCiAgICB1bmlxdWUoKSAlPiUKICAgIGdncGxvdCguLCBhZXMoeD10eXBlX2RheSwgeSA9IHNlZ19kZWxldGlvbl9yaWNobmVzcywgY29sb3IgPSBzZWdtZW50LCBncm91cD1zZWdtZW50KSkgKyAKICAgICNnZW9tX2JveHBsb3QoKSArIAogICAgZ2VvbV9saW5lKHNpemUgPSAxKSArIAogICAgZ2VvbV9wb2ludChzaXplID0gMikgKyAKICAgIGxhYnMoeD0nZHBpIChieSBpbmRleCBjYXNlKScsIHk9J0RWRyByaWNobmVzcycpICsgCiAgICBQbG90VGhlbWUxICsKICAgIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gJ1NldDInKSArCiAgICAjRGlldGNvbFNjYWxlICsgCiAgICBmYWNldF9ncmlkKC5+cGFpcl9udW1iZXJzLCBzY2FsZXMgPSAnZnJlZScsIHNwYWNlID0gJ2ZyZWUnKQoKcHJpbnQocDQpCgoKZ2dzYXZlKHA0LAogICAgICAgZmlsZW5hbWUgPSBnbHVlKCJ7d2tkaXJ9L0RWR19maWd1cmVzL3NlZ21lbnQub2Jlc2UudG8ub2Jlc2UucmljaG5lc3MucGRmIiksCiAgICAgICB3aWR0aCA9IDEyLAogICAgICAgaGVpZ2h0ID0gNCwgbGltaXRzaXplPUZBTFNFLCB1c2VEaW5nYmF0cyA9IEZBTFNFKQoKZ2dzYXZlKHA0LAogICAgICAgZmlsZW5hbWUgPSBnbHVlKCJ7d2tkaXJ9L0RWR19maWd1cmVzL3NlZ21lbnQub2Jlc2UudG8ub2Jlc2UucmljaG5lc3MucG5nIiksCiAgICAgICB3aWR0aCA9MTIsCiAgICAgICBoZWlnaHQgPSA0LCBsaW1pdHNpemU9RkFMU0UpICMsIHVzZURpbmdiYXRzID0gRkFMU0UpCmBgYAoKRW5kIG9mIEthdGUncyBjb2RlCgpXaGljaCBEVkdzIGFyZSBzaGFyZWQgYmV0d2VlbiBzdG9jayBhbmQgaW5kZXg/CmBgYHtyfQpyZXBzX2RmJERWRyA9IHBhc3RlMChyZXBzX2RmJHNlZ21lbnQsIl8iLHJlcHNfZGYkRFZHX2dyb3VwKQoKRjE3X3N0b2NrID0gZmlsdGVyKHJlcHNfZGYgLGluZl9yb3V0ZSA9PSAiQ29udHJvbCIsIGNvaG9ydCA9PSAiRjE3IikKRjE3X3N0b2NrX2R2ZyA9IHVuaXF1ZShGMTdfc3RvY2skRFZHKQpXMTdfc3RvY2sgPSBmaWx0ZXIocmVwc19kZiAsaW5mX3JvdXRlID09ICJDb250cm9sIiwgY29ob3J0ID09ICJXMTciKQpXMTdfc3RvY2tfZHZnID0gdW5pcXVlKFcxN19zdG9jayREVkcpClNtMThfc3RvY2sgPSBmaWx0ZXIocmVwc19kZiAsaW5mX3JvdXRlID09ICJDb250cm9sIiwgY29ob3J0ID09ICJTbTE4IikKU20xOF9zdG9ja19kdmcgPSB1bmlxdWUoU20xOF9zdG9jayREVkcpClNwMTlfc3RvY2sgPSBmaWx0ZXIocmVwc19kZiAsaW5mX3JvdXRlID09ICJDb250cm9sIiwgY29ob3J0ID09ICJTcDE5IikKU3AxOV9zdG9ja19kdmcgPSB1bmlxdWUoU3AxOV9zdG9jayREVkcpClNwMjBfc3RvY2sgPSBmaWx0ZXIocmVwc19kZiAsaW5mX3JvdXRlID09ICJDb250cm9sIiwgY29ob3J0ID09ICJTcDIwIikKU3AyMF9zdG9ja19kdmcgPSB1bmlxdWUoU3AyMF9zdG9jayREVkcpCgpGMTdfaW5kZXggPSBmaWx0ZXIocmVwc19kZiAsaW5mX3JvdXRlID09ICJJbmRleCIsIGNvaG9ydCA9PSAiRjE3IikKRjE3X2luZGV4X2R2ZyA9IHVuaXF1ZShGMTdfaW5kZXgkRFZHKQpXMTdfaW5kZXggPSBmaWx0ZXIocmVwc19kZiAsaW5mX3JvdXRlID09ICJJbmRleCIsIGNvaG9ydCA9PSAiVzE3IikKVzE3X2luZGV4X2R2ZyA9IHVuaXF1ZShXMTdfaW5kZXgkRFZHKQpTbTE4X2luZGV4ID0gZmlsdGVyKHJlcHNfZGYgLGluZl9yb3V0ZSA9PSAiSW5kZXgiLCBjb2hvcnQgPT0gIlNtMTgiKQpTbTE4X2luZGV4X2R2ZyA9IHVuaXF1ZShTbTE4X2luZGV4JERWRykKU3AxOV9pbmRleCA9IGZpbHRlcihyZXBzX2RmICxpbmZfcm91dGUgPT0gIkluZGV4IiwgY29ob3J0ID09ICJTcDE5IikKU3AxOV9pbmRleF9kdmcgPSB1bmlxdWUoU3AxOV9pbmRleCREVkcpClNwMjBfaW5kZXggPSBmaWx0ZXIocmVwc19kZiAsaW5mX3JvdXRlID09ICJJbmRleCIsIGNvaG9ydCA9PSAiU3AyMCIpClNwMjBfaW5kZXhfZHZnID0gdW5pcXVlKFNwMjBfaW5kZXgkRFZHKQoKRjE3X3NoYXJlZCA9IEYxN19pbmRleCAlPiUgZmlsdGVyKERWRyAlaW4lIEYxN19zdG9ja19kdmcpICU+JSBmaWx0ZXIoKERWRyAlaW4lIEYxN19pbmRleF9kdmcpKSAlPiUgdW5pcXVlKCkKRjE3X2Rlbm92byA9IEYxN19pbmRleCAlPiUgZmlsdGVyKChEVkcgJWluJSBGMTdfaW5kZXhfZHZnKSkgJT4lIGZpbHRlcighKERWRyAlaW4lIEYxN19zdG9ja19kdmcpKSAlPiUgdW5pcXVlKCkKClcxN19zaGFyZWQgPSBXMTdfaW5kZXggJT4lIGZpbHRlcihEVkcgJWluJSBXMTdfc3RvY2tfZHZnKSAlPiUgZmlsdGVyKChEVkcgJWluJSBXMTdfaW5kZXhfZHZnKSkgJT4lIHVuaXF1ZSgpClcxN19kZW5vdm8gPSBXMTdfaW5kZXggJT4lIGZpbHRlcigoRFZHICVpbiUgVzE3X2luZGV4X2R2ZykpICU+JSBmaWx0ZXIoIShEVkcgJWluJSBXMTdfc3RvY2tfZHZnKSkgJT4lIHVuaXF1ZSgpCgpTbTE4X3NoYXJlZCA9IFNtMThfaW5kZXggJT4lIGZpbHRlcihEVkcgJWluJSBTbTE4X3N0b2NrX2R2ZykgJT4lIGZpbHRlcigoRFZHICVpbiUgU20xOF9pbmRleF9kdmcpKSAlPiUgdW5pcXVlKCkKU20xOF9kZW5vdm8gPSBTbTE4X2luZGV4ICU+JSBmaWx0ZXIoKERWRyAlaW4lIFNtMThfaW5kZXhfZHZnKSkgJT4lIGZpbHRlcighKERWRyAlaW4lIFNtMThfc3RvY2tfZHZnKSkgJT4lIHVuaXF1ZSgpCgpTcDE5X3NoYXJlZCA9IFNwMTlfaW5kZXggJT4lIGZpbHRlcihEVkcgJWluJSBTcDE5X3N0b2NrX2R2ZykgJT4lIGZpbHRlcigoRFZHICVpbiUgU3AxOV9pbmRleF9kdmcpKSAlPiUgdW5pcXVlKCkKU3AxOV9kZW5vdm8gPSBTcDE5X2luZGV4ICU+JSBmaWx0ZXIoKERWRyAlaW4lIFNwMTlfaW5kZXhfZHZnKSkgJT4lIGZpbHRlcighKERWRyAlaW4lIFNwMTlfc3RvY2tfZHZnKSkgJT4lIHVuaXF1ZSgpCgpTcDIwX3NoYXJlZCA9IFNwMjBfaW5kZXggJT4lIGZpbHRlcihEVkcgJWluJSBTcDIwX3N0b2NrX2R2ZykgJT4lIGZpbHRlcigoRFZHICVpbiUgU3AyMF9pbmRleF9kdmcpKSAlPiUgdW5pcXVlKCkgIyBzdGlsbCBub3Qgd29ya2luZwpTcDIwX2Rlbm92byA9IFNwMjBfaW5kZXggJT4lIGZpbHRlcigoRFZHICVpbiUgU3AyMF9pbmRleF9kdmcpKSAlPiUgZmlsdGVyKCEoRFZHICVpbiUgU3AyMF9zdG9ja19kdmcpKSAlPiUgdW5pcXVlKCkgIyBzdGlsbCBub3Qgd29ya2luZwoKc3RvY2tfc2hhcmVkID0gcmJpbmQoRjE3X3NoYXJlZCxXMTdfc2hhcmVkLFNtMThfc2hhcmVkLFNwMTlfc2hhcmVkLFNwMjBfc2hhcmVkKQppbmRleF91bmlxdWUgPSByYmluZChGMTdfZGVub3ZvLFcxN19kZW5vdm8sU20xOF9kZW5vdm8sU3AxOV9kZW5vdm8sU3AyMF9kZW5vdm8pCmBgYAoKYGBge3J9CnN0b2NrX29iZXNlID0gZmlsdGVyKHN0b2NrX3NoYXJlZCwgZGlldCA9PSAiT2Jlc2UiKSAKb19kdmcgPSB1bmlxdWUoc3RvY2tfb2Jlc2UkRFZHKQoKc3RvY2tfbGVhbiA9IGZpbHRlcihzdG9ja19zaGFyZWQsIGRpZXQgPT0gIkxlYW4iKSAKbF9kdmcgPSB1bmlxdWUoc3RvY2tfbGVhbiREVkcpCgpzdG9ja19kdmcgPC0gbGlzdChPYmVzZSA9IG9fZHZnLCBMZWFuID0gbF9kdmcpCgpTdG9ja0RWR3MgPSBnZ1Zlbm5EaWFncmFtKHN0b2NrX2R2ZykKcHJpbnQoU3RvY2tEVkdzKQpnZ3NhdmUoU3RvY2tEVkdzLCBmaWxlID0gIlN0b2NrRFZHcy5wZGYiLCBwYXRoID0gc2F2ZWl0ZGlyKQoKI1Nob2NrU2hhcmVkRFZHcyA9IGdncGxvdChzdG9ja19zaGFyZWQsIGFlcyh4ID0gZHBpLCB5ID0gRFZHKSkgKwojICBnZW9tX3BvaW50KCkgKwojICBnZW9tX2xpbmUoYWVzKGdyb3VwID0gRFZHKSkgKwojICBmYWNldF9ncmlkKH5zZWdtZW50KSArCiMgIFBsb3RUaGVtZTEKI3ByaW50KFNob2NrU2hhcmVkRFZHcykKI2dnc2F2ZShTaG9ja1NoYXJlZERWR3MsIGZpbGUgPSAiU2hvY2tTaGFyZWREVkdzLnBkZiIsIHBhdGggPSBzYXZlaXRkaXIpCmBgYApBcmUgdGhlcmUgZGlldC1zcGVjaWZpYyBEVkdzIGluIGluZGV4IGZlcnJldHM/CmBgYHtyfQppbmRleF9vYmVzZSA9IGZpbHRlcihpbmRleF91bmlxdWUsIGRpZXQgPT0gIk9iZXNlIikgCm9fZHZnID0gdW5pcXVlKGluZGV4X29iZXNlJERWRykKCmluZGV4X2xlYW4gPSBmaWx0ZXIoaW5kZXhfdW5pcXVlLCBkaWV0ID09ICJMZWFuIikgCmxfZHZnID0gdW5pcXVlKGluZGV4X2xlYW4kRFZHKQoKZGlldF9kdmcgPC0gbGlzdChPYmVzZSA9IG9fZHZnLCBMZWFuID0gbF9kdmcpCgpEaWV0VW5pcXVlRFZHcyA9IGdnVmVubkRpYWdyYW0oZGlldF9kdmcpCnByaW50KERpZXRVbmlxdWVEVkdzKQpnZ3NhdmUoRGlldFVuaXF1ZURWR3MsIGZpbGUgPSAiRGlldFVuaXF1ZURWR3MucGRmIiwgcGF0aCA9IHNhdmVpdGRpcikKYGBgCgpQdWxsaW5nIG91dCBkaWV0LXNwZWNpZmljIERWR3MKYGBge3J9CmxlYW4gPSBpbmRleF9sZWFuICU+JSAKICBmaWx0ZXIoRFZHICVpbiUgbF9kdmcpICU+JSAKICBmaWx0ZXIoIShEVkcgJWluJSBvX2R2ZykpICU+JQogIHVuaXF1ZSgpCgpsZWFuID0gbGVhbiAlPiUKICBncm91cF9ieShEVkcpICU+JSAKICBtdXRhdGUoY291bnQgPSAxLCB0b3RhbHNhbXAgPSBzdW0oY291bnQpKQoKbXVsdF9sZWFuID0gZmlsdGVyKGxlYW4sIHRvdGFsc2FtcCA+IDEpICU+JSAKICB1bmlxdWUoKQoKb2Jlc2UgPSBpbmRleF91bmlxdWUgJT4lIAogIGZpbHRlcigoRFZHICVpbiUgb19kdmcpKSAlPiUKICBmaWx0ZXIoIShEVkcgJWluJSBsX2R2ZykpICU+JSAKICB1bmlxdWUoKQoKb2Jlc2UgPSBvYmVzZSAlPiUKICBncm91cF9ieShEVkcpICU+JSAKICBtdXRhdGUoY291bnQgPSAxLCB0b3RhbHNhbXAgPSBzdW0oY291bnQpKQoKbXVsdF9vYmVzZSA9IGZpbHRlcihvYmVzZSwgdG90YWxzYW1wID4gMSkgJT4lIAogIHVuaXF1ZSgpCmBgYAoKYGBge3J9CmxlYW5fdW5pcXVlcyA9IGxlYW4gJT4lCiAgdW5ncm91cCgpICU+JSAKICBzZWxlY3Qoc2VnbWVudCxEVkdfZ3JvdXAsR3JvdXBCb3VuZGFyaWVzLHRvdGFsc2FtcCkgJT4lIAogIHVuaXF1ZSgpICU+JSAKICBhcnJhbmdlKGRlc2ModG90YWxzYW1wKSkKCm9iZXNlX3VuaXF1ZXMgPSBvYmVzZSAlPiUKICB1bmdyb3VwKCkgJT4lIAogIHNlbGVjdChzZWdtZW50LERWR19ncm91cCxHcm91cEJvdW5kYXJpZXMsdG90YWxzYW1wKSAlPiUgCiAgdW5pcXVlKCkgJT4lIAogIGFycmFuZ2UoZGVzYyh0b3RhbHNhbXApKQpgYGAKCmBgYHtyfQpsZWFuX0RWR19zaXplcyA9IGxlYW4gJT4lIHVuZ3JvdXAgJT4lIHNlbGVjdChEVkcsRFZHX2dyb3VwLCBEZWxldGlvblNpemUsIE5ld1N0YXJ0LCBOZXdFbmQsIGRpZXQpICU+JSAKICB1bmlxdWUoKSAlPiUgCiAgYXJyYW5nZShkZXNjKERlbGV0aW9uU2l6ZSkpICU+JQogIG11dGF0ZShuYW1lID0gZmFjdG9yKERWRywgbGV2ZWxzID0gdW5pcXVlKERWRykpKQoKI2dncGxvdChsZWFuX0RWR19zaXplcywgYWVzKHggPSBEZWxldGlvblNpemUsIHkgPSBuYW1lKSkgKwojICBnZW9tX2NvbCgpICsKICAjZmFjZXRfZ3JpZChzZWdtZW50fnN0cmFpbikgKwojICBQbG90VGhlbWUxCiNnZ3NhdmUoInRlc3RfZHZnLnBkZiIsIGEsIHBhdGggPSBzYXZlaXRkaXIsIGhlaWdodCA9IDMwLCB3aWR0aCA9IDUpCgojbGVhbl9EVkdfc2l6ZXNfcGxvdCA9IGdncGxvdChsZWFuX0RWR19zaXplcywgYWVzKHggPSBOZXdTdGFydCwgeGVuZCA9IE5ld0VuZCwgeSA9IG5hbWUsIHllbmQgPSBuYW1lLCBjb2xvciA9IGRpZXQpKSArCiMgIGdlb21fc2VnbWVudCgpICsKICAjZmFjZXRfZ3JpZChzZWdtZW50fnN0cmFpbikgKwojICBQbG90VGhlbWUxICArCiMgIERpZXRjb2xTY2FsZQojcHJpbnQobGVhbl9EVkdfc2l6ZXNfcGxvdCkKI2dnc2F2ZSgibGVhbl9EVkdfc2l6ZXNfcGxvdC5wZGYiLGxlYW5fRFZHX3NpemVzX3Bsb3QsIHBhdGggPSBzYXZlaXRkaXIsIGhlaWdodCA9IDEwLCB3aWR0aCA9IDEwKQoKbGVhbl9EVkdfc2l6ZV9zZWcgPSBsZWFuICU+JSB1bmdyb3VwICU+JSBzZWxlY3QoRFZHLERWR19ncm91cCwgRGVsZXRpb25TaXplLCBOZXdTdGFydCwgTmV3RW5kLCBzZWdtZW50LGRpZXQpICU+JSAKICB1bmlxdWUoKSAlPiUgCiAgYXJyYW5nZShkZXNjKHNlZ21lbnQpLGRlc2MoRGVsZXRpb25TaXplKSkgJT4lCiAgbXV0YXRlKG5hbWUgPSBmYWN0b3IoRFZHLCBsZXZlbHMgPSB1bmlxdWUoRFZHKSkpCgpsZWFuX0RWR19zaXplX3NlZ19wbG90ID0gZ2dwbG90KGZpbHRlcihsZWFuX0RWR19zaXplX3NlZywgRGVsZXRpb25TaXplID4gNDAwKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSBOZXdTdGFydCwgeGVuZCA9IE5ld0VuZCwgeSA9IG5hbWUsIHllbmQgPSBuYW1lLCBjb2xvciA9IGRpZXQpKSArCiAgZ2VvbV9zZWdtZW50KCkgKwogIGZhY2V0X2dyaWQofnNlZ21lbnQpICsKICBQbG90VGhlbWUxICsKICBEaWV0Y29sU2NhbGUKcHJpbnQobGVhbl9EVkdfc2l6ZV9zZWdfcGxvdCkKZ2dzYXZlKCJsZWFuX0RWR19zaXplX3NlZ19wbG90LnBkZiIsbGVhbl9EVkdfc2l6ZV9zZWdfcGxvdCxwYXRoID0gc2F2ZWl0ZGlyLCBoZWlnaHQgPSAxMCwgd2lkdGggPSAxMCkKCmxlYW5faW5kZWxzX3NpemVfc2VnX3Bsb3QgPSBnZ3Bsb3QoZmlsdGVyKGxlYW5fRFZHX3NpemVfc2VnLCBEZWxldGlvblNpemUgPCA0MDApLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IE5ld1N0YXJ0LCB4ZW5kID0gTmV3RW5kLCB5ID0gbmFtZSwgeWVuZCA9IG5hbWUsIGNvbG9yID0gZGlldCkpICsKICBnZW9tX3NlZ21lbnQoKSArCiAgZmFjZXRfZ3JpZCh+c2VnbWVudCkgKwogIFBsb3RUaGVtZTEgKwogIERpZXRjb2xTY2FsZQpwcmludChsZWFuX2luZGVsc19zaXplX3NlZ19wbG90KQpnZ3NhdmUoImxlYW5faW5kZWxzX3NpemVfc2VnX3Bsb3QucGRmIixsZWFuX2luZGVsc19zaXplX3NlZ19wbG90LHBhdGggPSBzYXZlaXRkaXIsIGhlaWdodCA9IDEwLCB3aWR0aCA9IDEwKQpgYGAKCmBgYHtyfQpvYmVzZV9EVkdfc2l6ZXMgPSBvYmVzZSAlPiUgdW5ncm91cCAlPiUgc2VsZWN0KERWRyxEVkdfZ3JvdXAsIERlbGV0aW9uU2l6ZSwgTmV3U3RhcnQsIE5ld0VuZCwgZGlldCkgJT4lIAogIHVuaXF1ZSgpICU+JSAKICBhcnJhbmdlKGRlc2MoRGVsZXRpb25TaXplKSkgJT4lCiAgbXV0YXRlKG5hbWUgPSBmYWN0b3IoRFZHLCBsZXZlbHMgPSB1bmlxdWUoRFZHKSkpCgojZ2dwbG90KG9iZXNlX0RWR19zaXplcywgYWVzKHggPSBEZWxldGlvblNpemUsIHkgPSBuYW1lKSkgKwojICBnZW9tX2NvbCgpICsKICAjZmFjZXRfZ3JpZChzZWdtZW50fnN0cmFpbikgKwojICBQbG90VGhlbWUxIAojZ2dzYXZlKCJ0ZXN0X2R2Zy5wZGYiLCBhLCBwYXRoID0gc2F2ZWl0ZGlyLCBoZWlnaHQgPSAzMCwgd2lkdGggPSA1KQoKI29iZXNlX0RWR19zaXplc19wbG90ID0gZ2dwbG90KG9iZXNlX0RWR19zaXplcywgYWVzKHggPSBOZXdTdGFydCwgeGVuZCA9IE5ld0VuZCwgeSA9IG5hbWUsIHllbmQgPSBuYW1lLCBjb2xvciA9IGRpZXQpKSArCiMgIGdlb21fc2VnbWVudCgpICsKICAjZmFjZXRfZ3JpZChzZWdtZW50fnN0cmFpbikgKwojICBQbG90VGhlbWUxICsKIyAgRGlldGNvbFNjYWxlCiNwcmludChvYmVzZV9EVkdfc2l6ZXNfcGxvdCkKI2dnc2F2ZSgib2Jlc2VfRFZHX3NpemVzX3Bsb3QucGRmIixvYmVzZV9EVkdfc2l6ZXNfcGxvdCwgcGF0aCA9IHNhdmVpdGRpciwgaGVpZ2h0ID0gMTAsIHdpZHRoID0gMTApCgpvYmVzZV9EVkdfc2l6ZV9zZWcgPSBvYmVzZSAlPiUgdW5ncm91cCAlPiUgc2VsZWN0KERWRyxEVkdfZ3JvdXAsIERlbGV0aW9uU2l6ZSwgTmV3U3RhcnQsIE5ld0VuZCwgc2VnbWVudCxkaWV0KSAlPiUgCiAgdW5pcXVlKCkgJT4lIAogIGFycmFuZ2UoZGVzYyhzZWdtZW50KSxkZXNjKERlbGV0aW9uU2l6ZSkpICU+JQogIG11dGF0ZShuYW1lID0gZmFjdG9yKERWRywgbGV2ZWxzID0gdW5pcXVlKERWRykpKQoKb2Jlc2VfRFZHX3NpemVfc2VnX3Bsb3QgPSBnZ3Bsb3QoZmlsdGVyKG9iZXNlX0RWR19zaXplX3NlZywgRGVsZXRpb25TaXplID4gNDAwKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gTmV3U3RhcnQsIHhlbmQgPSBOZXdFbmQsIHkgPSBuYW1lLCB5ZW5kID0gbmFtZSwgY29sb3IgPSBkaWV0KSkgKwogIGdlb21fc2VnbWVudCgpICsKICBmYWNldF9ncmlkKH5zZWdtZW50KSArCiAgUGxvdFRoZW1lMSAgKwogIERpZXRjb2xTY2FsZQpwcmludChvYmVzZV9EVkdfc2l6ZV9zZWdfcGxvdCkKZ2dzYXZlKCJvYmVzZV9EVkdfc2l6ZV9zZWdfcGxvdC5wZGYiLG9iZXNlX0RWR19zaXplX3NlZ19wbG90LCBwYXRoID0gc2F2ZWl0ZGlyLCBoZWlnaHQgPSAxMCwgd2lkdGggPSAxMCkKCm9iZXNlX2luZGVsc19zaXplX3NlZ19wbG90ID0gZ2dwbG90KGZpbHRlcihvYmVzZV9EVkdfc2l6ZV9zZWcsIERlbGV0aW9uU2l6ZSA8IDQwMCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IE5ld1N0YXJ0LCB4ZW5kID0gTmV3RW5kLCB5ID0gbmFtZSwgeWVuZCA9IG5hbWUsIGNvbG9yID0gZGlldCkpICsKICBnZW9tX3NlZ21lbnQoKSArCiAgZmFjZXRfZ3JpZCh+c2VnbWVudCkgKwogIFBsb3RUaGVtZTEgICsKICBEaWV0Y29sU2NhbGUKcHJpbnQob2Jlc2VfaW5kZWxzX3NpemVfc2VnX3Bsb3QpCmdnc2F2ZSgib2Jlc2VfaW5kZWxzX3NpemVfc2VnX3Bsb3QucGRmIixvYmVzZV9pbmRlbHNfc2l6ZV9zZWdfcGxvdCwgcGF0aCA9IHNhdmVpdGRpciwgaGVpZ2h0ID0gMTAsIHdpZHRoID0gMTApCmBgYAoKQXJlIERWR3MgdHJhbnNtaXR0ZWQ/CmBgYHtyfQpkdmdfZGYgPSBzZWxlY3QocmVwc19kZiwgZmVycmV0X2RheSwgZmVycmV0X2lkLCBkcGksIGRpZXQsIGluZl9yb3V0ZSwgc2VnbWVudCwgRFZHX2dyb3VwLCBHcm91cEJvdW5kYXJpZXMsIHBhaXJfZGlldHMsIHBhaXJfbnVtYmVycykgJT4lCiAgdW5ncm91cCgpICU+JQogIHVuaXF1ZSgpCmR2Z19kZiRzZWdfZHZnID0gcGFzdGUwKGR2Z19kZiRzZWdtZW50LCJfIixkdmdfZGYkRFZHX2dyb3VwKQoKaW5kZXggPSBmaWx0ZXIoZHZnX2RmLCBpbmZfcm91dGUgPT0gIkluZGV4IikgJT4lIHVuaXF1ZSgpCmZpcnN0X3RpbWUgPSBjKCIxNzk0X2QwNCIsIjE3OTdfZDAyIiwiMTkxM19kMDYiLCIxOTE0X2QwNiIsIjE5ODBfZDAyIiwiMTk4MV9kMTAiLCIxOTg2X2QxMCIsIjIyMzFfZDA2IiwiMjIzMl9kMDIiLCIyMjM5X2QwMiIpCmVhcmx5X3RpbWUgPSBjKCIxNzk0X2QwNCIsIjE3OTdfZDAyIiwiMTk4MF9kMDIiLCIyMjMyX2QwMiIsIjIyMzlfZDAyIikKZGlyZWN0ID0gZmlsdGVyKGR2Z19kZiwgZmVycmV0X2RheSAlaW4lIGZpcnN0X3RpbWUpICU+JSB1bmlxdWUoKQogCnNhbXBsZXMgPSB1bmlxdWUoaW5kZXgkZmVycmV0X2RheSkKICAKZHZnX3RyYW5zbWl0dGVkID0gZGF0YS5mcmFtZSgpCiAgCmZvcihpIGluIHNhbXBsZXMpewogIHByaW50KGkpCiAgCiAgbiA9IGZpbHRlcihpbmRleCwgZmVycmV0X2RheSA9PSBpKQogIHBhcnRuZXIgPSB1bmlxdWUobiRwYWlyX251bWJlcnMpCiAgZCA9IGZpbHRlcihkaXJlY3QsIHBhaXJfbnVtYmVycyAlaW4lIHBhcnRuZXIpCiAgCiAgaWYobnJvdyhkKSA+IDApewogICAgCiAgICBzID0gdW5pcXVlKGQkZmVycmV0X2RheSkKICAgIHByaW50KHMpCiAgCiAgICBjb21wID0gbWVyZ2UobiwgZCwgYnkgPSBjKCJwYWlyX2RpZXRzIiwicGFpcl9udW1iZXJzIiwic2VnbWVudCIsInNlZ19kdmciLCJEVkdfZ3JvdXAiLCJHcm91cEJvdW5kYXJpZXMiKSwgYWxsLnggPSBUUlVFKSAlPiUKICAgICAgZHBseXI6OmNvdW50KHBhaXJfbnVtYmVycyxmZXJyZXRfZGF5LngsIGZlcnJldF9kYXkueSkKICAgIGNvbG5hbWVzKGNvbXApID0gYygicGFpcl9udW1iZXJzIiwiSW5kZXgiLCJDb250YWN0IiwiY291bnQiKQogICAgIAogICAgZHZnX3RyYW5zbWl0dGVkID0gcmJpbmQoZHZnX3RyYW5zbWl0dGVkLCBjb21wKQogICAKICB9ZWxzZShwcmludCgiTm8gdHJhbnNtaXNzaW9uIikpCiAgCn0KCiNkdmdfdHJhbnNtaXR0ZWQgPSBkdmdfdHJhbnNtaXR0ZWQgJT4lIAojICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gY29udGFjdCwgdmFsdWVzX2Zyb20gPSBjb3VudCkKYGBgCgpgYGB7cn0KIGNvbnRhY3RfZHZncyA9IGZpbHRlcihkdmdfZGYsIGluZl9yb3V0ZSA9PSAiSW5kZXgiKSAlPiUgZHBseXI6OmNvdW50KGZlcnJldF9pZCxkcGksZGlldCkgJT4lCiAgZ2dwbG90KC4sIGFlcyh4ID0gZHBpLCB5ID0gbiwgY29sb3IgPSBkaWV0KSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9saW5lKGFlcyhncm91cCA9IGZlcnJldF9pZCkpICsKICBmYWNldF9ncmlkKH5mZXJyZXRfaWQpICsKICB5bGFiKCJEVkcgcmljaG5lc3MiKSArCiAgeGxhYigiRFBJIikgKwogIFBsb3RUaGVtZTEgKwogIERpZXRjb2xTY2FsZQpwcmludChjb250YWN0X2R2Z3MpCmdnc2F2ZShjb250YWN0X2R2Z3MsIGZpbGUgPSAiY29udGFjdF9kdmdzLnBkZiIsIHBhdGggPSBzYXZlaXRkaXIpCmBgYAo=